commit d9e9fcc2e302b27a3e894d24a1ba11d82bb496a2 Author: thkim Date: Tue Dec 30 15:01:58 2025 +0900 Init diff --git a/KICT.html b/KICT.html new file mode 100644 index 0000000..05fa61f --- /dev/null +++ b/KICT.html @@ -0,0 +1,124 @@ + + + + + 지반정보 DB 포털 + + + +

◎액상화 위험지도 다운로드

+

액상화 위험지도는 DXF 또는 Shape 파일로 지역별로 제공되며 3D 데이터를 보기 위해서는 전용 뷰어가 필요합니다.

+ +

전용 뷰어 다운로드

+ +
+

◎액상화 위험지도 현황

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
번호위치지반증폭자료LPI/LSN
1부산시 강서구
2부산시 강서구 가락동
3부산시 강서구 강동동
4세종특별자치시 도담동
5세종특별자치시 소담동
6세종특별자치시 새롬동
+ +
+ + + diff --git a/Liquefaction_download.html b/Liquefaction_download.html new file mode 100644 index 0000000..61ce20c --- /dev/null +++ b/Liquefaction_download.html @@ -0,0 +1,128 @@ + + + + + 지반정보 DB 포털 + + + +

◎액상화 위험지도 다운로드

+
+

액상화 위험지도는 DXF 또는 Shape 파일로 지역별로 제공되며 3D 데이터를 보기 위해서는 전용 뷰어가 필요합니다.

+ +

전용 뷰어 다운로드

+
+
+

◎액상화 위험지도 현황

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
번호위치지반증폭자료LPI/LSN
1부산광역시(500년)
2부산광역시(1000년)
3부산광역시(2400년)
4세종특별자치시(500년)
5세종특별자치시(1000년)
6세종특별자치시(2400년)
+ +
+ + + diff --git a/RnD_deep.html b/RnD_deep.html new file mode 100644 index 0000000..e225c05 --- /dev/null +++ b/RnD_deep.html @@ -0,0 +1,147 @@ + + + + + + +
+

Start of Content

+
+ + +
+
+
    +
  • REFERENCE
  • +
  • + 혁신적인 기술 다양한 솔루션제공, 고객감동을 추구하는 기업 디비엔텍입니다 +
  • +
+
+
+
+ +
+
+ REFERENCE 》 딥러닝 기반 사고영상 감지 시스템 +
+
+
+ +

>

+
+ +
+ +
    + +
  • +
  • +
    +
    딥러닝 기반 사고영상 감지 시스템
    +
    + 딥러닝 기반 사고영상 감지 시스템은 CCTV 감시 범위 내 이동 및 목표객체를 자동 인식하고 + 관리지침에 지정되어 있는 사고, 역주행, 화재 등의 비상상황을 자동인지 및 경보하는 시스템. + 컴퓨터 비전 기반 영상분석 기법과 비교해 날씨나 장소에 영향을 적게 받으며, + 더 높은 정확도로 사고 인식 +
    +
    +
      +
    • 첫 비디오
    • +
    • 두번째 비디오
    • +
    • 세번째 비디오
    • + +
    +
    +
    +
  • +
+ +
+
+
    +
  • 1) 기술 소개 : 딥러닝 기반 사고영상 감지 시스템
  • +
  • + 객체 검출(Object Detection)은 영상 정보를 사람 대신 컴퓨터로 분석하는 대표적인 연구 분야입니다. + 객체 검출 기술은 CCTV 영상을 분석함으로써 보행자 감지, 차량 및 표지판 인식 등 우리의 일상생활 안에서 + 다양하게 활용되고 있습니다. 특히 교통류 모니터링 분야에서는 CCTV를 활용한 전국 도로망의 상시 모니터링이 이루어지고 있습니다. + 일부 주요 구간에서는 교통정체, 충돌사고, 낙하물 발생 등 돌발 상황들을 자동으로 인식하여 알려주는 사고감지 시스템이 운용되고 있습니다. + 기존의 사고감지 시스템은 전통적인 컴퓨터 비전 기술 기반의 알고리즘이 탑재되어 있는데 조도나 날씨와 같이 주변 환경의 변화에 대단히 민감하게 + 반응하여 미탐 또는 오탐이 빈번하게 발생하는 문제점이 있습니다. + 디비엔텍에서는 이와 같은 문제점을 해결하기 위해 딥러닝 기반 객체 검출 기술을 활용하여 여러 환경의 영상 속에서도 사람처럼 영상 내 객체 검출이 가능한 + 사고 감지 시스템을 개발하였습니다. 한국건설기술연구원과의 협업으로 다양한 환경에 최적화된 사고감지 시스템을 완성하여 2019년부터 시스템을 시범설치 및 납품하여 운영중입니다. +
  • +
+
    +
  • 2) 관련 이미지
  • +
  • + 레티나넷 + SSD and YOLO +
  • +
+
    +
  • 3) 딥러닝 기반 객체 검출의 활용 방안
  • +
  • +
    +
    가. CCTV 영상 분석을 통한 비정상 사건(유고) 검출
    +
    +
    + 1. 정차(또는 추돌), 역주행 감지
    + 2. 보행자 감지
    + 3. 화재, 연기 감지
    +
    +
    +
    +
    나. 이미지 내 문자 검출
    +
    +
    + 1. 카드 번호 인식
    + 2. 차량 번호판 인식
    +
    +
    +
    +
    다. 공간 내 객체 인식
    +
    +
    + 1. 무인 점포 결제 시스템을 위한 상품 인식
    + 2. 냉장고 내 재고 자동 파악
    +
    +
    +
    +
    라. 행동 패턴 분석
    +
    +
    + 1. 사람의 움직임 추적
    + 2. 사람의 행동 반경 산출
    +
    +
    +
  • +
+
+ +
+ +
+ +
+ +
+ + +
+ + + + + diff --git a/RnD_koreaRoad.html b/RnD_koreaRoad.html new file mode 100644 index 0000000..2494cee --- /dev/null +++ b/RnD_koreaRoad.html @@ -0,0 +1,119 @@ + + + + + + +
+

Start of Content

+
+ + +
+
+
    +
  • REFERENCE
  • +
  • + 혁신적인 기술 다양한 솔루션제공, 고객감동을 추구하는 기업 디비엔텍입니다 +
  • +
+
+
+
+ +
+
+ REFERENCE 》 도로표지관리/안내시스템 +
+
+
+ +

<

+
+ +
+ +
    +
  • +
  • +
    +
    도로표지관리/안내시스템
    +
    + 전국 300여개 도로관리청이 웹 상에서 도로표지 정보를 + 관리하는「도로표지 관리 및 안내 시스템」으로 도로표지를 + 등록/관리 함은 물론 도로표지를 분석하여 위치 및 안내정보의 + 적정성 분석, 검토/보완 신청 및 각종 검색과 통계 기능을 통하여 + 도로표지 정보현황에 관한 종합적인 파악 및 정책결정의 판단근거에 + 사용. 또한, 도로표지를 적정하게 제작, 설치 및 유지관리하기 위해 + 도로표지 도안을 유형별로 표준화하여 체계적이고 합리적인 도로표지 + 자동도안 프로그램(RoadGuider)을 개발. (www.roadsign.go.kr) +
    +
    +
      +
    • +
    • +
    • +
    +
    +
    +
  • +
+ +
+
+
    +
  • 1) 기술 소개 : 도로표지시스템(관리시스템 및 안내시스템)
  • +
  • + 도로표지는 차량 운전자 등 도로이용자에게 목적지까지 방향, 거리, 경로안내 및 기타 정보를 제공함으로써 안전하고 원활한 도로교통을 확보함은 물론 도로의 이용효율을 극대화 할 수 있는 중요한 도로 부속물입니다. 도로표지시스템(관리시스템 및 안내시스템)은 한국건설기술연구원의 도로표지운영센터에서 운영중인 도로표지에 관한 전반적인 관리를 수행 및 조회할 수 있는 시스템으로 당사는 도로표지시스템의 원활한 운영을 위해 시스템 유지보수 및 사용자의 다양한 요구에 따른 기능 개선 업무를 수행하며, 시스템 운영의 기반이 되는 도로망도의 갱신 업무를 수행하고 있습니다. 특히, 도로표지시스템을 선형 기반의 관리 수준으로 고도화하고, 선형을 활용한 분석 기능 강화 및 신설 도로표지 설계에 대한 의사 결정을 지원하는 시스템으로 발전시켜 왔습니다. 도로표지시스템은 300여 도로표지 관리 기관들이 도로표지를 입력하고 관리할 수 있는 도로표지관리시스템(www.korearoadsign.go.kr)과 일반인들이 도로표지를 언제든지 검색 조회할수 있는 도로표지안내시스템(www.roadsign.go.kr)로 나뉘어 서비스를 제공하고 있습니다. +
  • +
  • 2) 선형기반 관리 시스템
  • +
  • + 선형 기반 도로표지시스템은 도로표지 데이터를 모두 도로의 선형(노선)에 링크시켜 노선 단위로 표지를 관리하는 시스템입니다. + 선형 기반 시스템의 장점은 모든 표지를 자동으로 도로의 선형 정보에 연결시키므로써 도로 선형 정보로부터 일관된 정보를 매칭시킴으로써 오류 제거 및 무결성을 높일 수 있으며 경로탐색 등의 결과에 의해 상하행 등을 구분하고 일관성 있는 데이터 추출을 보장시킬 수 있습니다. + +
  • +
  • 3) 오류표지 검출 기능
  • +
  • + 오류표지 검출 기능은 각 지역 담당자가 자신이 관리하는 표지 중 검토할 표지 목록을 좀 더 세분화하여 확인할 수 있는 기능으로 도로종별, 도로번호, 도로명, 관리기관, 소속불명 등의 잠재되어 있는 오류를 검출하여 주는 기능입니다. 오류표지는 붉은색 물음표 아이콘과 회색 아이콘을 조합하여 화면에 도시하여, 기존 표지와 구분이 용이하도록 하였고, 검색 조건으로 관리기관, 도로종별, 노선번호, 행정구역을 입력하여 원하는 오류표지 목록을 얻을 수 있으며, 행정구역 단위 오류표지 검색 기능을 추가하여 오류표지 관리 기능을 강화하였습니다.
    + +
  • +
  • 4) 의사결정지원 시스템
  • +
  • + 도로표지를 새롭게 신설하고자 한다면 자동으로 안내지명은 물론, 표지규격, 설치 위치 등을 자동으로 제시하는 기능으로 이러한 기능을 바탕으로 기존 입력된 표지에 대해서도 도로 선형 정보를 이용하여 안내지명 및 표지 규격을 검수할 수 있는 기능입니다. 뿐만아니라 교차로에서는 주변 거리를 표시하고 해당 거리내에 표지의 위치가 적합한지를 판단해 주는 기능 역시 도로 선형 정보를 통해 보다 정확하게 산출해 낼 수 있습니다. 또한 안내지명에 대하여 진행 방향 또는 교차로 연계성 분석을 통하여 이전 도로표지와 현재 도로표지의 안내지명 등이 일치하는지를 분석하여 줍니다.
    + +
  • + +
  • 5) 도로표지 도안 프로그램(로드가이더)
  • +
  • + 도로표지를 적정하게 제작, 설치 및 유지관리하기 위해서는 계획과 설계 단계에서부터 관련 법규나 규정에 의해 심도있게 검토하여 시행하여야 하며 따라서 도로표지 도안을 유형별로 표준화하여 체계적이고 합리적인 도로 안내체계를 수립하기 위한 프로그램으로 도로표지 도안 프로그램인 로드가이더(RoadGuider) 개발하였습니다. 로드가이더는 기존 안내지명 도로표지 뿐만아니라 도로명 표지의 기본 양식 및 체계를 반영하여 도로표지를 제작, 설치 및 관리하는 도로관리청의 실무자들이 보다 편리하고 체계적인 도로표지를 제작 및 관리할 있도록 하였습니다.
    + + +
  • +
+ +
+ +
+ +
+ +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/RnD_lunar.html b/RnD_lunar.html new file mode 100644 index 0000000..247cdd5 --- /dev/null +++ b/RnD_lunar.html @@ -0,0 +1,125 @@ + + + + + + +
+

Start of Content

+
+ + +
+
+
    +
  • REFERENCE
  • +
  • + 혁신적인 기술 다양한 솔루션제공, 고객감동을 추구하는 기업 디비엔텍입니다 +
  • +
+
+
+
+ +
+
+ REFERENCE 》 월면 크레이터 자동 인식 시스템 +
+
+
+ +
    +
  1. <
  2. +
  3. >
  4. +
+
+ +
+ +
    +
  • +
  • +
    +
    월면 크레이터 자동 인식 시스템
    +
    + 딥러닝 영상인식 기술을 이용하여 달 지상 이미지 객체를 인식하여 크레이터를 + 자동으로 탐지하는 시스템. 음영 기복을 적용한 DEM 이미지를 딥러닝 기반 객체 인식 기법의 학습하여 + 레이블링 되지 않은 크레이터도 다수 검출 가능해짐에 따라 고성능의 우주건설분야 지형 객체영상 처리 + 및 자동 통계화 기술 확보에 기여 +
    +
    +
      +
    • +
    • +
    • +
    +
    +
    +
  • +
+ +
+
+
    +
  • 1) 기술 소개 : 월면 크레이터 자동 인식 시스템
  • +
  • + 달 표면 크레이터 검출은 항공우주 분야에서 대단히 중요한 연구분야 중 하나입니다. 전통적으로 달 표면 크레이터 검출은 고해상도의 DEM(Digital Elevation Model) 이미지를 전문가가 육안으로 보고 판단하였습니다. 하지만 전문가 사이에서도 크레이터 검출 결과가 달라 검출 결과의 신뢰성과 일관성 유지에 어려움을 겪고 있었습니다. +㈜디비엔텍에서는 한국건설기술연구원의 위탁용역 사업으로 딥러닝 기반 객체 검출 기술을 활용한 자동 크레이터 검출 시스템에 대한 연구를 진행하였습니다. 육안으로 구분이 어려운 DEM 이미지 대신 음영기복(Hill Shade) 기법을 전처리로 활용하는 등 다양한 기법을 활용하여 딥러닝 모델의 객체 검출 성능을 높였습니다. 결과적으로 크고 작은 크레이터를 좀 더 정밀하게 검출할 수 있었을 뿐만 아니라 육안으로는 찾아내지 못했던 크레이터를 다수 검출하는 결과를 얻을 수 있었습니다. +이 연구결과는 우주건설분야 외에도 딥러닝 기반 객체인식을 활용한 건설 및 교통인프라 등 타 분야에도 활용할 수 있으며, 극한 환경 건설기술 활성화 및 미래 우주탐사 관련 신시장 창출에 공헌할 수 있을 것입니다. +
  • +
+
    +
  • 2) 실험결과
  • +
  • + 레티나넷 + SSD and YOLO + SSD and YOLO +
  • +
+
    +
  • 3) 딥러닝 기반 객체 검출의 활용 방안
  • +
  • +
    +
    가. 영상 기반 SOC 시설물 외관 상태 분석
    +
    +
    + 1. 열화, 균열, 파손 등의 상태 인식
    + 2. 영상 내 손상 위치 및 크기 파악 가능
    +
    +
    +
    +
    나. 이미지 내 문자 검출
    +
    +
    + 1. 딥러닝 기반 자동 품질 검사
    + 2. 딥러닝 기반 고장 진단(영상/소리)
    +
    +
    +
  • +
+
+ +
+ +
+ +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/RnD_module.html b/RnD_module.html new file mode 100644 index 0000000..ee2a5cc --- /dev/null +++ b/RnD_module.html @@ -0,0 +1,163 @@ + + + + + + +
+

Start of Content

+
+ + +
+
+
    +
  • REFERENCE
  • +
  • + 혁신적인 기술 다양한 솔루션제공, 고객감동을 추구하는 기업 디비엔텍입니다 +
  • +
+
+
+
+ +
+
+ REFERENCE 》 액상화 모델링 및 3차원 분석 모듈 +
+
+
+ +
    +
  1. <
  2. +
  3. >
  4. +
+
+ +
+ +
    +
  • +
  • +
    +
    시추정보 기반의 액상화모델링 및 3차원 분석모듈
    +
    + 국토지반정보 통합DB센터가 보유하고 있는 시추정보 추출의 효율화를 + 위해 액상화 분석 기초데이터 모델링 및 2·3차원의 액상화 분석맵 생성 + 모듈을 개발. 개발된 모듈을 통해 얻어진 액상화 분석 및 가시화 정보는 + 액상화 피해 예측 시스템으로 활용되어 지진 재해 대응, 지하안전관리 등 + 타 시스템과의 연계·활용 체계 구축에 활용이 가능하며, 안전시공, 지진 재해 + 대응 등 종합적인 의사결정 지원 체계 구축에 활용함. +
    +
    +
      +
    • +
    • +
    • +
    +
    +
    +
  • +
+ +
+
+
    +
  • 1) 기술 소개 : 액상화 모델링 및 3차원 분석 모듈
  • +
  • + 최근 포항에서 일어난 지진으로 액상화 현상이 공식적으로 확인된바가 있습니다. 액상화란 토양이 응력을 받았을 때 강성과 전단강도를 상실하여 액체처럼 되는 현상으로 일반적으로 액상화 현상이 발생하면 물과 모래의 일부가 땅 위로 분출되어 공간이 생길 수 있으므로 도로침하나 싱크홀 발생의 위험이 있습니다. 때문에, 국내에서도 액상화 위험지도 제작의 필요성이 커지고 있으며 본 연구는 액상화 위험지도 제작을 위한 전국 시추정보 관련 정보를 추출하고 이러한 시추정보를 바탕으로 기초데이터 모델링과 3차원 분석을 위한 모듈을 개발하였습니다. +
  • +
  • 2) 보간법
  • +
  • + 보간법(혹은 공간 보간법)은 알려진 데이터 지점을 이용하여 새로운 데이터 지점을 구성하는 방식입니다. 공간에 대한 통계 자료가 필요할 때 가장 좋은 방법은 모든 지점에서 필요로 하는 자료를 직접 획득하는 것이나 비용과 시간 등의 문제로 인하여 모든 지점에서 원하는 값을 얻는다는 것은 현실적으로 불가능합니다. 따라서 많은 특정 지점을 선정하여 관측값을 얻은 후 이 데이터를 이용하여 알고자 하는 지점의 값을 예측하는 방법이 사용되고 있으며, 이러한 과정에 보간법이 많이 이용됩니다. 본 시스템에서는 대표적인 다음과 같은 6가지 보간법을 제공하고 있습니다. +
  • +
+
    +
  • 3) 보간법 종류
  • +
  • +
    +
    가) 방사기반함수(Radial Basis Function, RBF)
    +
    + 다변량 데이터의 보간을 위해 제안된 모델로 크리깅에 비해 생성이 용이하고 비선형이 강한 시스템을 잘 표현해주나 예측 성능이 민감하게 반응하는 단점이 있다. +
    +
    +
    +
    나) 자연화소(Natural Neighbor) 보간법
    +
    + 이산 공간 집합의 Voronoi tessellation을 기반으로 한 보간법으로 가장 단순하며 비교적 근사치에 가까운 결과를 보여준다. +
    +
    +
    +
    다) 역거리 가중법 (Inverse Distance Weight, IDW)
    +
    + 주변의 가까운 점으로부터 선형으로 결합된 가중치를 사용하여 새로운 셀의 값을 결정하는 방법. 가까이 있는 실측값에 더 큰 가중치를 주어 보간하는 방법으로 거리가 가까울수록 높은 가중치가 적용되기 때문에 역거리 가중법이라고 한다. +
    +
    +
    +
    라) 크리깅(불규칙 삼각망)
    +
    + 이미 알고 있는 데이터들의 선형 조합으로 관심 있는 지점에서의 속성 값을 예측하는 지구 통계학적 방법으로 주위의 실측값들을 선형으로 조합하여 통계학적인 방법을 이용하여 값을 추정. 값을 추정할 때 실측값과의 거리뿐만 아니라 주변에 이웃한 값 사이의 상관 강도를 반영. 많은 양의 계산이 필요하지만 비교적 정확하다. +
    +
    +
    +
    마) 불규칙 삼각망(Triagulated Irregular Network, TIN)
    +
    + 모든 점을 삼각형으로 연결하여 삼각형 내의 값을 계산하는 것으로 작은 영역에 비교적 적당하다. +
    +
    +
    +
    바) 스플라인(Spline) 보간법
    +
    + 자료 점들의 부분집합에 점차 다항식을 적용시켜 나가는 연결 다항식을 스플라인 함수라고 한다. 함수는 일반적으로 완만하게 변하지만, 특정 구역에서는 급격히 변하는 경우도 있다. 스플라인 함수는 국부적으로 급격히 변화하는 함수의 거동에 우수한 근사값을 제공한다. +
    +
    +
  • +
  • + +
  • +
+
    +
  • 4) 가시화
  • +
  • +
    +
    가. Surface 가시화
    +
    +
    + surface 가시화 기능은 일정 간격으로 보정된 지반 저항치 R을 가시화 하는 기능입니다. 지반 저항치 surface 가시화를 클릭하면 다음 그림과 같이 지반 저항치 surface 가시화가 된 화면이 출력됩니다. +
    +
    +
    +
    나. 3D 가시화
    +
    +
    + 3D 가시화 기능은 지반 저항치 2D 분석 결과를 바탕으로 3D 저항치 값에 대한 모델링을 하고 이를 입체적으로 화면에 도시하는 기능입니다. 도시된 화면은 확대/축소/회전 등이 가능하며 각 저항치 값에 대한 Legend (범례)를 지원하여 시각화에 도움을 줍니다. 다음은 지반 저항치 2D 분석 결과를 3D cube형태로 가시화 하는 개념도입니다. +
    +
    +
  • +
+
+ +
+ +
+ +
+ +
+ + +
+ + + + + \ No newline at end of file diff --git a/ajax/demo-architecture-interior-ajax-load-more-2.html b/ajax/demo-architecture-interior-ajax-load-more-2.html new file mode 100644 index 0000000..22b4be0 --- /dev/null +++ b/ajax/demo-architecture-interior-ajax-load-more-2.html @@ -0,0 +1,45 @@ +
+ +
+
+ +
+
+ +
\ No newline at end of file diff --git a/ajax/demo-architecture-interior-ajax-load-more-3.html b/ajax/demo-architecture-interior-ajax-load-more-3.html new file mode 100644 index 0000000..36c98bb --- /dev/null +++ b/ajax/demo-architecture-interior-ajax-load-more-3.html @@ -0,0 +1,45 @@ +
+ +
+
+ +
+
+ +
\ No newline at end of file diff --git a/ajax/demo-architecture-interior-ajax-services-detail.html b/ajax/demo-architecture-interior-ajax-services-detail.html new file mode 100644 index 0000000..8f9c6da --- /dev/null +++ b/ajax/demo-architecture-interior-ajax-services-detail.html @@ -0,0 +1,30 @@ +
+
+
+

Home Projects

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ut nunc in enim laoreet ornare. Nullam tincidunt tempor ligula eu dignissim. Nam semper dui quis congue mollis. Nam at tellus ultricies, tincidunt quam non, rhoncus mauris. Nullam gravida molestie lorem, et euismod metus feugiat ac.

+
+
+
+
+
+ +
+
+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In ut nunc in enim laoreet ornare. Nullam tincidunt tempor ligula eu dignissim. Nam semper dui quis congue mollis.

+ +

CALL US NOW

+

1-800-123-4567

+
+
+
\ No newline at end of file diff --git a/ajax/demo-architecture-interior-ajax-team-detail.html b/ajax/demo-architecture-interior-ajax-team-detail.html new file mode 100644 index 0000000..32cb12d --- /dev/null +++ b/ajax/demo-architecture-interior-ajax-team-detail.html @@ -0,0 +1,17 @@ +
+
+
+ + +
+
+

Michele Doe

+

CEO & Founder

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. In dapibus risus sit amet malesuada placerat. Duis purus massa, luctus a egestas non, interdum eu mauris. Etiam efficitur nibh vitae viverra hendrerit.

Integer blandit dui nulla, vitae facilisis sapien elementum vitae. Quisque eu turpis ac lectus faucibus vehicula. Duis tincidunt ornare diam, ut pellentesque dolor dapibus quis. Sed tempus bibendum felis, et pharetra risus placerat vel. Duis vitae lorem risus. Aenean eu odio eu turpis elementum feugiat. Vivamus aliquet ac lorem a luctus. Vestibulum sed purus a justo finibus dictum sed in velit. Nullam at elementum nisl, eget tincidunt ligula. Quisque efficitur rhoncus nunc, quis rutrum ligula dapibus at. Sed rutrum placerat lectus in bibendum.

+
+
+
\ No newline at end of file diff --git a/ajax/demo-architecture-interior-blog-ajax-load-more-2.html b/ajax/demo-architecture-interior-blog-ajax-load-more-2.html new file mode 100644 index 0000000..3c89bf7 --- /dev/null +++ b/ajax/demo-architecture-interior-blog-ajax-load-more-2.html @@ -0,0 +1,48 @@ +
+
+
+
+

+ Lorem ipsum dolor sit amet, consectetur +

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget risus porta...

+
+ + by Alex Doe +
+
+
+
+
+
+
+
+
+

+ Lorem ipsum dolor sit amet, consectetur +

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget risus porta...

+
+ + by Rick Doe +
+
+
+
+
+
+
+
+
+

+ Lorem ipsum dolor sit amet, consectetur +

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget risus porta...

+
+ + by John Doe +
+
+
+
+
\ No newline at end of file diff --git a/ajax/demo-architecture-interior-blog-ajax-load-more-3.html b/ajax/demo-architecture-interior-blog-ajax-load-more-3.html new file mode 100644 index 0000000..1d818e9 --- /dev/null +++ b/ajax/demo-architecture-interior-blog-ajax-load-more-3.html @@ -0,0 +1,32 @@ +
+
+
+
+

+ Lorem ipsum dolor sit amet, consectetur +

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget risus porta...

+
+ + by Alex Doe +
+
+
+
+
+
+
+
+
+

+ Lorem ipsum dolor sit amet, consectetur +

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed eget risus porta...

+
+ + by Rick Doe +
+
+
+
+
\ No newline at end of file diff --git a/ajax/demo-church-gallery-ajax-on-page-1.html b/ajax/demo-church-gallery-ajax-on-page-1.html new file mode 100644 index 0000000..f52069d --- /dev/null +++ b/ajax/demo-church-gallery-ajax-on-page-1.html @@ -0,0 +1,15 @@ +

+ Baptism +

+

3 photos

+ \ No newline at end of file diff --git a/ajax/demo-church-gallery-ajax-on-page-2.html b/ajax/demo-church-gallery-ajax-on-page-2.html new file mode 100644 index 0000000..689bf23 --- /dev/null +++ b/ajax/demo-church-gallery-ajax-on-page-2.html @@ -0,0 +1,15 @@ +

+ Wedding +

+

3 photos

+ \ No newline at end of file diff --git a/ajax/demo-church-gallery-ajax-on-page-3.html b/ajax/demo-church-gallery-ajax-on-page-3.html new file mode 100644 index 0000000..e22a677 --- /dev/null +++ b/ajax/demo-church-gallery-ajax-on-page-3.html @@ -0,0 +1,15 @@ +

+ Church Community +

+

3 photos

+ \ No newline at end of file diff --git a/ajax/demo-construction-2-ajax-projects-load-more-2.html b/ajax/demo-construction-2-ajax-projects-load-more-2.html new file mode 100644 index 0000000..2295904 --- /dev/null +++ b/ajax/demo-construction-2-ajax-projects-load-more-2.html @@ -0,0 +1,22 @@ +
+ +
+
+ +
\ No newline at end of file diff --git a/ajax/demo-construction-2-ajax-projects-load-more-3.html b/ajax/demo-construction-2-ajax-projects-load-more-3.html new file mode 100644 index 0000000..72b7ac6 --- /dev/null +++ b/ajax/demo-construction-2-ajax-projects-load-more-3.html @@ -0,0 +1,44 @@ +
+ +
+
+ +
+
+ +
+
+ +
\ No newline at end of file diff --git a/ajax/demo-it-services-ajax-load-more-2.html b/ajax/demo-it-services-ajax-load-more-2.html new file mode 100644 index 0000000..8509be7 --- /dev/null +++ b/ajax/demo-it-services-ajax-load-more-2.html @@ -0,0 +1,22 @@ +
+
+
+ + Okler Success Case + +

OKLER SUCCESS CASE

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc viverra erat orci, ac auctor.

+
+
+
+
+
+
+ + Porto Master Case + +

PORTO MASTER CASE

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc viverra erat orci, ac auctor.

+
+
+
\ No newline at end of file diff --git a/ajax/demo-it-services-ajax-load-more-3.html b/ajax/demo-it-services-ajax-load-more-3.html new file mode 100644 index 0000000..a2dd203 --- /dev/null +++ b/ajax/demo-it-services-ajax-load-more-3.html @@ -0,0 +1,22 @@ +
+
+
+ + Porto Master Case + +

PORTO MASTER CASE

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc viverra erat orci, ac auctor.

+
+
+
+
+
+
+ + Okler Success Case + +

OKLER SUCCESS CASE

+

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc viverra erat orci, ac auctor.

+
+
+
\ No newline at end of file diff --git a/ajax/demo-one-page-agency-ajax-load-more-2.html b/ajax/demo-one-page-agency-ajax-load-more-2.html new file mode 100644 index 0000000..280f55f --- /dev/null +++ b/ajax/demo-one-page-agency-ajax-load-more-2.html @@ -0,0 +1,60 @@ +
+ +
+
+ +
+
+ +
+
+ +
\ No newline at end of file diff --git a/ajax/demo-one-page-agency-ajax-load-more-3.html b/ajax/demo-one-page-agency-ajax-load-more-3.html new file mode 100644 index 0000000..b1ca2e7 --- /dev/null +++ b/ajax/demo-one-page-agency-ajax-load-more-3.html @@ -0,0 +1,60 @@ +
+ +
+
+ +
+
+ +
+
+ +
\ No newline at end of file diff --git a/ajax/demo-photography-portfolio-ajax-on-page-load-more.html b/ajax/demo-photography-portfolio-ajax-on-page-load-more.html new file mode 100644 index 0000000..4c73809 --- /dev/null +++ b/ajax/demo-photography-portfolio-ajax-on-page-load-more.html @@ -0,0 +1,208 @@ +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ + + 6 + + + + +
+ + +
+
New Born
+
+
+
+
+
+
+ +
+
+ +
+
+
+ + + 7 + + + + +
+ + +
+
The Day
+
+
+
+
+
\ No newline at end of file diff --git a/ajax/demo-photography-portfolio-ajax-on-page-slider.html b/ajax/demo-photography-portfolio-ajax-on-page-slider.html new file mode 100644 index 0000000..22a9d6c --- /dev/null +++ b/ajax/demo-photography-portfolio-ajax-on-page-slider.html @@ -0,0 +1,91 @@ +
+
+
    +
  • + + +
    The Explorers
    +
  • +
  • + + +
    The Happy Family
    +
  • +
  • + + +
    The Cool Style
    +
  • +
  • + + +
    The Bride
    +
  • +
  • + + +
    The Landscape
    +
  • +
+
+
\ No newline at end of file diff --git a/ajax/demo-photography-portfolio-infinite-scroll-load-more.html b/ajax/demo-photography-portfolio-infinite-scroll-load-more.html new file mode 100644 index 0000000..16e6dc8 --- /dev/null +++ b/ajax/demo-photography-portfolio-infinite-scroll-load-more.html @@ -0,0 +1,53 @@ +
+ +
+
+ +
+
+ +
+
+ +
\ No newline at end of file diff --git a/ajax/index-blog-4-ajax-load-more-2.html b/ajax/index-blog-4-ajax-load-more-2.html new file mode 100644 index 0000000..cb169ac --- /dev/null +++ b/ajax/index-blog-4-ajax-load-more-2.html @@ -0,0 +1,168 @@ + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
\ No newline at end of file diff --git a/ajax/index-blog-4-ajax-load-more-3.html b/ajax/index-blog-4-ajax-load-more-3.html new file mode 100644 index 0000000..75b2b7e --- /dev/null +++ b/ajax/index-blog-4-ajax-load-more-3.html @@ -0,0 +1,28 @@ + +
+ +
\ No newline at end of file diff --git a/ajax/portfolio-ajax-load-more-2.html b/ajax/portfolio-ajax-load-more-2.html new file mode 100644 index 0000000..c2ddaef --- /dev/null +++ b/ajax/portfolio-ajax-load-more-2.html @@ -0,0 +1,72 @@ +
+ +
+
+ +
+
+ +
+
+ +
\ No newline at end of file diff --git a/ajax/portfolio-ajax-load-more-3.html b/ajax/portfolio-ajax-load-more-3.html new file mode 100644 index 0000000..6f79eae --- /dev/null +++ b/ajax/portfolio-ajax-load-more-3.html @@ -0,0 +1,72 @@ +
+ +
+
+ +
+
+ +
+
+ +
\ No newline at end of file diff --git a/ajax/portfolio-ajax-project-1.html b/ajax/portfolio-ajax-project-1.html new file mode 100644 index 0000000..b86bf46 --- /dev/null +++ b/ajax/portfolio-ajax-project-1.html @@ -0,0 +1,70 @@ +
+ + +
+
+ +
+ +
+ +
+ + Share + + +
+
+

Project Description

+

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

+ +

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin ipsum tortor, viverra ut condimentum eu, accumsan a enim. Etiam egestas purus risus, vulputate ullamcorper diam fermentum in. Pellentesque non libero hendrerit, vestibulum tellus ut, malesuada purus.

+ +

Project Details

+ +
+
+
\ No newline at end of file diff --git a/ajax/portfolio-ajax-project-2.html b/ajax/portfolio-ajax-project-2.html new file mode 100644 index 0000000..6c7d0e1 --- /dev/null +++ b/ajax/portfolio-ajax-project-2.html @@ -0,0 +1,70 @@ +
+ + +
+
+ +
+ +
+ +
+ + Share + + +
+
+

Project Description

+

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

+ +

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin ipsum tortor, viverra ut condimentum eu, accumsan a enim. Etiam egestas purus risus, vulputate ullamcorper diam fermentum in. Pellentesque non libero hendrerit, vestibulum tellus ut, malesuada purus.

+ +

Project Details

+ +
+
+
\ No newline at end of file diff --git a/ajax/portfolio-ajax-project-3.html b/ajax/portfolio-ajax-project-3.html new file mode 100644 index 0000000..0beff85 --- /dev/null +++ b/ajax/portfolio-ajax-project-3.html @@ -0,0 +1,70 @@ +
+ + +
+
+ +
+ +
+ +
+ + Share + + +
+
+

Project Description

+

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

+ +

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin ipsum tortor, viverra ut condimentum eu, accumsan a enim. Etiam egestas purus risus, vulputate ullamcorper diam fermentum in. Pellentesque non libero hendrerit, vestibulum tellus ut, malesuada purus.

+ +

Project Details

+ +
+
+
\ No newline at end of file diff --git a/ajax/portfolio-ajax-project-4.html b/ajax/portfolio-ajax-project-4.html new file mode 100644 index 0000000..fbd8c5b --- /dev/null +++ b/ajax/portfolio-ajax-project-4.html @@ -0,0 +1,70 @@ +
+ + +
+
+ +
+ +
+ +
+ + Share + + +
+
+

Project Description

+

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

+ +

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin ipsum tortor, viverra ut condimentum eu, accumsan a enim. Etiam egestas purus risus, vulputate ullamcorper diam fermentum in. Pellentesque non libero hendrerit, vestibulum tellus ut, malesuada purus.

+ +

Project Details

+ +
+
+
\ No newline at end of file diff --git a/ajax/portfolio-ajax-project-5.html b/ajax/portfolio-ajax-project-5.html new file mode 100644 index 0000000..157f170 --- /dev/null +++ b/ajax/portfolio-ajax-project-5.html @@ -0,0 +1,70 @@ +
+ + +
+
+ +
+ +
+ +
+ + Share + + +
+
+

Project Description

+

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

+ +

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin ipsum tortor, viverra ut condimentum eu, accumsan a enim. Etiam egestas purus risus, vulputate ullamcorper diam fermentum in. Pellentesque non libero hendrerit, vestibulum tellus ut, malesuada purus.

+ +

Project Details

+ +
+
+
\ No newline at end of file diff --git a/ajax/portfolio-ajax-project-6.html b/ajax/portfolio-ajax-project-6.html new file mode 100644 index 0000000..6d953f0 --- /dev/null +++ b/ajax/portfolio-ajax-project-6.html @@ -0,0 +1,70 @@ +
+ + +
+
+ +
+ +
+ +
+ + Share + + +
+
+

Project Description

+

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

+ +

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin ipsum tortor, viverra ut condimentum eu, accumsan a enim. Etiam egestas purus risus, vulputate ullamcorper diam fermentum in. Pellentesque non libero hendrerit, vestibulum tellus ut, malesuada purus.

+ +

Project Details

+ +
+
+
\ No newline at end of file diff --git a/ajax/portfolio-ajax-project-7.html b/ajax/portfolio-ajax-project-7.html new file mode 100644 index 0000000..dcddb09 --- /dev/null +++ b/ajax/portfolio-ajax-project-7.html @@ -0,0 +1,70 @@ +
+ + +
+
+ +
+ +
+ +
+ + Share + + +
+
+

Project Description

+

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

+ +

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin ipsum tortor, viverra ut condimentum eu, accumsan a enim. Etiam egestas purus risus, vulputate ullamcorper diam fermentum in. Pellentesque non libero hendrerit, vestibulum tellus ut, malesuada purus.

+ +

Project Details

+ +
+
+
\ No newline at end of file diff --git a/ajax/portfolio-ajax-project.html b/ajax/portfolio-ajax-project.html new file mode 100644 index 0000000..b8252a1 --- /dev/null +++ b/ajax/portfolio-ajax-project.html @@ -0,0 +1,82 @@ +
+ + +
+
+ + + +
+ + Share + + +
+
+

Project Description

+

Donec volutpat nibh sit amet libero ornare non laoreet arcu luctus. Donec id arcu quis mauris euismod placerat sit amet ut metus. Sed imperdiet fringilla sem eget euismod. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.

+ +

Project Details

+ +
+
+
\ No newline at end of file diff --git a/business01.html b/business01.html new file mode 100644 index 0000000..f89bacf --- /dev/null +++ b/business01.html @@ -0,0 +1,63 @@ + + + + +
+

Start of Content

+
+ + +
+
+
    +
  • BUSINESS
  • +
  • 인간의 삶과 행복을 추구하는 인간중심 기업 디비엔텍입니다
  • +
+
+
+
+ +
+
+ + BUSINESS 》 AI & BigData +
+
+ +
+ + + +
+

>

+
+
    +
  • AI & BigData
  • +
  • + 딥러닝(Deep-Learning) 기반 CCTV 영상 실시간 객체인식 및 유형 분석
    + 시스템 엔진 개발 +
  • +
  • + 자가학습을 통한 딥러닝 기술을 이용한 사고 감지 시스템 개발 +
  • +
  • + 딥러닝 영상처리 기반 SOC 시설물 상태 모니터링 시스템 개발 및 상시 운영 지원 컨설팅 +
  • +
  • + 머신러닝(Machine-Learning) 기반 맞춤형 문서 빅데이터 처리 시스템 개발 +
  • +
+ +
+ +
+ + + +
+
+ + + + + \ No newline at end of file diff --git a/business02.html b/business02.html new file mode 100644 index 0000000..7db8f79 --- /dev/null +++ b/business02.html @@ -0,0 +1,70 @@ + + + + +
+

Start of Content

+
+ + +
+
+
    +
  • BUSINESS
  • +
  • 인간의 삶과 행복을 추구하는 인간중심 기업 디비엔텍입니다
  • +
+
+
+
+ +
+
+ BUSINESS 》 Smart SOC +
+
+ +
+ + + +
+
    +
  1. <
  2. +
  3. >
  4. +
+
+
    +
  • Smart SOC
  • +
  • + 빅데이터(Data), 초고속네트워크(Network), 인공지능(AI)의 + DNA 기술을 + 활용한 스마트 SOC 지원 기술 개발 +
  • +
  • + ICT 기반의 각종 SOC 시설물(도로, 사면, 터널, 교량 등) 영상 + 모니터링 및
    + 현황 정보화 +
  • +
  • + 재난 및 각종 사고로부터 시민을 보호하는 지능화 기술을 활용한 + SOC 혁신
    + 기술 개발 +
  • +
  • + 스마트 안전 사회 구축을 위한 각종 솔루션 개발 +
  • +
+ +
+ +
+ + + +
+
+ + + + + \ No newline at end of file diff --git a/business03.html b/business03.html new file mode 100644 index 0000000..b48005d --- /dev/null +++ b/business03.html @@ -0,0 +1,66 @@ + + + + +
+

Start of Content

+
+ + +
+
+
    +
  • BUSINESS
  • +
  • 인간의 삶과 행복을 추구하는 인간중심 기업 디비엔텍입니다
  • +
+
+
+
+ +
+
+ BUSINESS 》 IT Service +
+
+ +
+ + +
+

<

+
+
    +
  • IT Service
  • +
  • + SOC, 교통, 안전, 서비스부문 시스템 및 플랫폼 구축 및 운영 +
  • + +
  • + E-Commerce, SNS, ERP, 기업용 업무지원 솔루션 등 + 온라인플랫폼
    + 구축 및 운영 +
  • + +
  • + Network 및 영상 통합 보안 관제 서비스 +
  • + +
  • + Open API, SDK 등 통합 서비스 플랫폼 설계 / 구축 +
  • +
  • + 정보 시스템 아웃소싱(ITO)을 통한 신기술, 도구, + 전문가 등의 기술 이전 +
  • +
+ +
+ +
+
+
+ + + + + \ No newline at end of file diff --git a/common/PEAR/Archive/Tar.php b/common/PEAR/Archive/Tar.php new file mode 100644 index 0000000..ce6c88b --- /dev/null +++ b/common/PEAR/Archive/Tar.php @@ -0,0 +1,1601 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Tar.php,v 1.13.4.8 2004/01/26 01:26:45 pajoye Exp $ + +require_once 'PEAR.php'; + +/** +* Creates a (compressed) Tar archive +* +* @author Vincent Blavet +* @version $Revision: 1.13.4.8 $ +* @package Archive +*/ +class Archive_Tar extends PEAR +{ + /** + * @var string Name of the Tar + */ + var $_tarname=''; + + /** + * @var boolean if true, the Tar file will be gzipped + */ + var $_compress=false; + + /** + * @var string Type of compression : 'none', 'gz' or 'bz2' + */ + var $_compress_type='none'; + + /** + * @var file descriptor + */ + var $_file=0; + + /** + * @var string Local Tar name of a remote Tar (http:// or ftp://) + */ + var $_temp_tarname=''; + + // {{{ constructor + /** + * Archive_Tar Class constructor. This flavour of the constructor only + * declare a new Archive_Tar object, identifying it by the name of the + * tar file. + * If the compress argument is set the tar will be read or created as a + * gzip or bz2 compressed TAR file. + * + * @param string $p_tarname The name of the tar archive to create + * @param string $p_compress can be null, 'gz' or 'bz2'. This + * parameter indicates if gzip or bz2 compression + * is required. For compatibility reason the + * boolean value 'true' means 'gz'. + * @access public + */ + function Archive_Tar($p_tarname, $p_compress = null) + { + $this->PEAR(); + $this->_compress = false; + $this->_compress_type = 'none'; + if ($p_compress === null) { + if (@file_exists($p_tarname)) { + if ($fp = @fopen($p_tarname, "rb")) { + // look for gzip magic cookie + $data = fread($fp, 2); + fclose($fp); + if ($data == "\37\213") { + $this->_compress = true; + $this->_compress_type = 'gz'; + // No sure it's enought for a magic code .... + } elseif ($data == "BZ") { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + } else { + // probably a remote file or some file accessible + // through a stream interface + if (substr($p_tarname, -2) == 'gz') { + $this->_compress = true; + $this->_compress_type = 'gz'; + } elseif ((substr($p_tarname, -3) == 'bz2') || + (substr($p_tarname, -2) == 'bz')) { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + } else { + if (($p_compress == true) || ($p_compress == 'gz')) { + $this->_compress = true; + $this->_compress_type = 'gz'; + } else if ($p_compress == 'bz2') { + $this->_compress = true; + $this->_compress_type = 'bz2'; + } + } + $this->_tarname = $p_tarname; + if ($this->_compress) { // assert zlib or bz2 extension support + if ($this->_compress_type == 'gz') + $extname = 'zlib'; + else if ($this->_compress_type == 'bz2') + $extname = 'bz2'; + + if (!extension_loaded($extname)) { + PEAR::loadExtension($extname); + } + if (!extension_loaded($extname)) { + die("The extension '$extname' couldn't be found.\n". + "Please make sure your version of PHP was built ". + "with '$extname' support.\n"); + return false; + } + } + } + // }}} + + // {{{ destructor + function _Archive_Tar() + { + $this->_close(); + // ----- Look for a local copy to delete + if ($this->_temp_tarname != '') + @unlink($this->_temp_tarname); + $this->_PEAR(); + } + // }}} + + // {{{ create() + /** + * This method creates the archive file and add the files / directories + * that are listed in $p_filelist. + * If a file with the same name exist and is writable, it is replaced + * by the new tar. + * The method return false and a PEAR error text. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * For each directory added in the archive, the files and + * sub-directories are also added. + * See also createModify() method for more details. + * + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @return true on success, false on error. + * @see createModify() + * @access public + */ + function create($p_filelist) + { + return $this->createModify($p_filelist, '', ''); + } + // }}} + + // {{{ add() + /** + * This method add the files / directories that are listed in $p_filelist in + * the archive. If the archive does not exist it is created. + * The method return false and a PEAR error text. + * The files and directories listed are only added at the end of the archive, + * even if a file with the same name is already archived. + * See also createModify() method for more details. + * + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @return true on success, false on error. + * @see createModify() + * @access public + */ + function add($p_filelist) + { + return $this->addModify($p_filelist, '', ''); + } + // }}} + + // {{{ extract() + function extract($p_path='') + { + return $this->extractModify($p_path, ''); + } + // }}} + + // {{{ listContent() + function listContent() + { + $v_list_detail = array(); + + if ($this->_openRead()) { + if (!$this->_extractList('', $v_list_detail, "list", '', '')) { + unset($v_list_detail); + $v_list_detail = 0; + } + $this->_close(); + } + + return $v_list_detail; + } + // }}} + + // {{{ createModify() + /** + * This method creates the archive file and add the files / directories + * that are listed in $p_filelist. + * If the file already exists and is writable, it is replaced by the + * new tar. It is a create and not an add. If the file exists and is + * read-only or is a directory it is not replaced. The method return + * false and a PEAR error text. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * The path indicated in $p_remove_dir will be removed from the + * memorized path of each file / directory listed when this path + * exists. By default nothing is removed (empty path '') + * The path indicated in $p_add_dir will be added at the beginning of + * the memorized path of each file / directory listed. However it can + * be set to empty ''. The adding of a path is done after the removing + * of path. + * The path add/remove ability enables the user to prepare an archive + * for extraction in a different path than the origin files are. + * See also addModify() method for file adding properties. + * + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @param string $p_add_dir A string which contains a path to be added to the + * memorized path of each element in the list. + * @param string $p_remove_dir A string which contains a path to be removed from + * the memorized path of each element in the list, when + * relevant. + * @return boolean true on success, false on error. + * @access public + * @see addModify() + */ + function createModify($p_filelist, $p_add_dir, $p_remove_dir='') + { + $v_result = true; + + if (!$this->_openWrite()) + return false; + + if ($p_filelist != '') { + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode(" ", $p_filelist); + else { + $this->_cleanFile(); + $this->_error('Invalid file list'); + return false; + } + + $v_result = $this->_addList($v_list, $p_add_dir, $p_remove_dir); + } + + if ($v_result) { + $this->_writeFooter(); + $this->_close(); + } else + $this->_cleanFile(); + + return $v_result; + } + // }}} + + // {{{ addModify() + /** + * This method add the files / directories listed in $p_filelist at the + * end of the existing archive. If the archive does not yet exists it + * is created. + * The $p_filelist parameter can be an array of string, each string + * representing a filename or a directory name with their path if + * needed. It can also be a single string with names separated by a + * single blank. + * The path indicated in $p_remove_dir will be removed from the + * memorized path of each file / directory listed when this path + * exists. By default nothing is removed (empty path '') + * The path indicated in $p_add_dir will be added at the beginning of + * the memorized path of each file / directory listed. However it can + * be set to empty ''. The adding of a path is done after the removing + * of path. + * The path add/remove ability enables the user to prepare an archive + * for extraction in a different path than the origin files are. + * If a file/dir is already in the archive it will only be added at the + * end of the archive. There is no update of the existing archived + * file/dir. However while extracting the archive, the last file will + * replace the first one. This results in a none optimization of the + * archive size. + * If a file/dir does not exist the file/dir is ignored. However an + * error text is send to PEAR error. + * If a file/dir is not readable the file/dir is ignored. However an + * error text is send to PEAR error. + * + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @param string $p_add_dir A string which contains a path to be added to the + * memorized path of each element in the list. + * @param string $p_remove_dir A string which contains a path to be removed from + * the memorized path of each element in the list, when + * relevant. + * @return true on success, false on error. + * @access public + */ + function addModify($p_filelist, $p_add_dir, $p_remove_dir='') + { + $v_result = true; + + if (!@is_file($this->_tarname)) + $v_result = $this->createModify($p_filelist, $p_add_dir, $p_remove_dir); + else { + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode(" ", $p_filelist); + else { + $this->_error('Invalid file list'); + return false; + } + + $v_result = $this->_append($v_list, $p_add_dir, $p_remove_dir); + } + + return $v_result; + } + // }}} + + // {{{ addString() + /** + * This method add a single string as a file at the + * end of the existing archive. If the archive does not yet exists it + * is created. + * + * @param string $p_filename A string which contains the full filename path + * that will be associated with the string. + * @param string $p_string The content of the file added in the archive. + * @return true on success, false on error. + * @access public + */ + function addString($p_filename, $p_string) + { + $v_result = true; + + if (!@is_file($this->_tarname)) { + if (!$this->_openWrite()) { + return false; + } + $this->_close(); + } + + if (!$this->_openAppend()) + return false; + + // Need to check the get back to the temporary file ? .... + $v_result = $this->_addString($p_filename, $p_string); + + $this->_writeFooter(); + + $this->_close(); + + return $v_result; + } + // }}} + + // {{{ extractModify() + /** + * This method extract all the content of the archive in the directory + * indicated by $p_path. When relevant the memorized path of the + * files/dir can be modified by removing the $p_remove_path path at the + * beginning of the file/dir path. + * While extracting a file, if the directory path does not exists it is + * created. + * While extracting a file, if the file already exists it is replaced + * without looking for last modification date. + * While extracting a file, if the file already exists and is write + * protected, the extraction is aborted. + * While extracting a file, if a directory with the same name already + * exists, the extraction is aborted. + * While extracting a directory, if a file with the same name already + * exists, the extraction is aborted. + * While extracting a file/directory if the destination directory exist + * and is write protected, or does not exist but can not be created, + * the extraction is aborted. + * If after extraction an extracted file does not show the correct + * stored file size, the extraction is aborted. + * When the extraction is aborted, a PEAR error text is set and false + * is returned. However the result can be a partial extraction that may + * need to be manually cleaned. + * + * @param string $p_path The path of the directory where the files/dir need to by + * extracted. + * @param string $p_remove_path Part of the memorized path that can be removed if + * present at the beginning of the file/dir path. + * @return boolean true on success, false on error. + * @access public + * @see extractList() + */ + function extractModify($p_path, $p_remove_path) + { + $v_result = true; + $v_list_detail = array(); + + if ($v_result = $this->_openRead()) { + $v_result = $this->_extractList($p_path, $v_list_detail, "complete", 0, $p_remove_path); + $this->_close(); + } + + return $v_result; + } + // }}} + + // {{{ extractInString() + /** + * This method extract from the archive one file identified by $p_filename. + * The return value is a string with the file content, or NULL on error. + * @param string $p_filename The path of the file to extract in a string. + * @return a string with the file content or NULL. + * @access public + */ + function extractInString($p_filename) + { + if ($this->_openRead()) { + $v_result = $this->_extractInString($p_filename); + $this->_close(); + } else { + $v_result = NULL; + } + + return $v_result; + } + // }}} + + // {{{ extractList() + /** + * This method extract from the archive only the files indicated in the + * $p_filelist. These files are extracted in the current directory or + * in the directory indicated by the optional $p_path parameter. + * If indicated the $p_remove_path can be used in the same way as it is + * used in extractModify() method. + * @param array $p_filelist An array of filenames and directory names, or a single + * string with names separated by a single blank space. + * @param string $p_path The path of the directory where the files/dir need to by + * extracted. + * @param string $p_remove_path Part of the memorized path that can be removed if + * present at the beginning of the file/dir path. + * @return true on success, false on error. + * @access public + * @see extractModify() + */ + function extractList($p_filelist, $p_path='', $p_remove_path='') + { + $v_result = true; + $v_list_detail = array(); + + if (is_array($p_filelist)) + $v_list = $p_filelist; + elseif (is_string($p_filelist)) + $v_list = explode(" ", $p_filelist); + else { + $this->_error('Invalid string list'); + return false; + } + + if ($v_result = $this->_openRead()) { + $v_result = $this->_extractList($p_path, $v_list_detail, "partial", $v_list, $p_remove_path); + $this->_close(); + } + + return $v_result; + } + // }}} + + // {{{ _error() + function _error($p_message) + { + // ----- To be completed + $this->raiseError($p_message); + } + // }}} + + // {{{ _warning() + function _warning($p_message) + { + // ----- To be completed + $this->raiseError($p_message); + } + // }}} + + // {{{ _openWrite() + function _openWrite() + { + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($this->_tarname, "wb"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($this->_tarname, "wb"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($this->_tarname, "wb"); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in write mode \''.$this->_tarname.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _openRead() + function _openRead() + { + if (strtolower(substr($this->_tarname, 0, 7)) == 'http://') { + + // ----- Look if a local copy need to be done + if ($this->_temp_tarname == '') { + $this->_temp_tarname = uniqid('tar').'.tmp'; + if (!$v_file_from = @fopen($this->_tarname, 'rb')) { + $this->_error('Unable to open in read mode \''.$this->_tarname.'\''); + $this->_temp_tarname = ''; + return false; + } + if (!$v_file_to = @fopen($this->_temp_tarname, 'wb')) { + $this->_error('Unable to open in write mode \''.$this->_temp_tarname.'\''); + $this->_temp_tarname = ''; + return false; + } + while ($v_data = @fread($v_file_from, 1024)) + @fwrite($v_file_to, $v_data); + @fclose($v_file_from); + @fclose($v_file_to); + } + + // ----- File to open if the local copy + $v_filename = $this->_temp_tarname; + + } else + // ----- File to open if the normal Tar file + $v_filename = $this->_tarname; + + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($v_filename, "rb"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($v_filename, "rb"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($v_filename, "rb"); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in read mode \''.$v_filename.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _openReadWrite() + function _openReadWrite() + { + if ($this->_compress_type == 'gz') + $this->_file = @gzopen($this->_tarname, "r+b"); + else if ($this->_compress_type == 'bz2') + $this->_file = @bzopen($this->_tarname, "r+b"); + else if ($this->_compress_type == 'none') + $this->_file = @fopen($this->_tarname, "r+b"); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + if ($this->_file == 0) { + $this->_error('Unable to open in read/write mode \''.$this->_tarname.'\''); + return false; + } + + return true; + } + // }}} + + // {{{ _close() + function _close() + { + if (isset($this->_file)) { + if ($this->_compress_type == 'gz') + @gzclose($this->_file); + else if ($this->_compress_type == 'bz2') + @bzclose($this->_file); + else if ($this->_compress_type == 'none') + @fclose($this->_file); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + $this->_file = 0; + } + + // ----- Look if a local copy need to be erase + // Note that it might be interesting to keep the url for a time : ToDo + if ($this->_temp_tarname != '') { + @unlink($this->_temp_tarname); + $this->_temp_tarname = ''; + } + + return true; + } + // }}} + + // {{{ _cleanFile() + function _cleanFile() + { + $this->_close(); + + // ----- Look for a local copy + if ($this->_temp_tarname != '') { + // ----- Remove the local copy but not the remote tarname + @unlink($this->_temp_tarname); + $this->_temp_tarname = ''; + } else { + // ----- Remove the local tarname file + @unlink($this->_tarname); + } + $this->_tarname = ''; + + return true; + } + // }}} + + // {{{ _writeBlock() + function _writeBlock($p_binary_data, $p_len=null) + { + if ($this->_file) { + if ($p_len === null) { + if ($this->_compress_type == 'gz') + @gzputs($this->_file, $p_binary_data); + else if ($this->_compress_type == 'bz2') + @bzwrite($this->_file, $p_binary_data); + else if ($this->_compress_type == 'none') + @fputs($this->_file, $p_binary_data); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + } else { + if ($this->_compress_type == 'gz') + @gzputs($this->_file, $p_binary_data, $p_len); + else if ($this->_compress_type == 'bz2') + @bzwrite($this->_file, $p_binary_data, $p_len); + else if ($this->_compress_type == 'none') + @fputs($this->_file, $p_binary_data, $p_len); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + } + } + return true; + } + // }}} + + // {{{ _readBlock() + function _readBlock($p_len=null) + { + $v_block = null; + if ($this->_file) { + if ($p_len === null) + $p_len = 512; + + if ($this->_compress_type == 'gz') + $v_block = @gzread($this->_file, 512); + else if ($this->_compress_type == 'bz2') + $v_block = @bzread($this->_file, 512); + else if ($this->_compress_type == 'none') + $v_block = @fread($this->_file, 512); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + } + return $v_block; + } + // }}} + + // {{{ _jumpBlock() + function _jumpBlock($p_len=null) + { + if ($this->_file) { + if ($p_len === null) + $p_len = 1; + + if ($this->_compress_type == 'gz') + @gzseek($this->_file, @gztell($this->_file)+($p_len*512)); + else if ($this->_compress_type == 'bz2') { + // ----- Replace missing bztell() and bzseek() + for ($i=0; $i<$p_len; $i++) + $this->_readBlock(); + } else if ($this->_compress_type == 'none') + @fseek($this->_file, @ftell($this->_file)+($p_len*512)); + else + $this->_error('Unknown or missing compression type ('.$this->_compress_type.')'); + + } + return true; + } + // }}} + + // {{{ _writeFooter() + function _writeFooter() + { + if ($this->_file) { + // ----- Write the last 0 filled block for end of archive + $v_binary_data = pack("a512", ''); + $this->_writeBlock($v_binary_data); + } + return true; + } + // }}} + + // {{{ _addList() + function _addList($p_list, $p_add_dir, $p_remove_dir) + { + $v_result=true; + $v_header = array(); + + // ----- Remove potential windows directory separator + $p_add_dir = $this->_translateWinPath($p_add_dir); + $p_remove_dir = $this->_translateWinPath($p_remove_dir, false); + + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if (sizeof($p_list) == 0) + return true; + + for ($j=0; ($j_tarname) + continue; + + if ($v_filename == '') + continue; + + if (!file_exists($v_filename)) { + $this->_warning("File '$v_filename' does not exist"); + continue; + } + + // ----- Add the file or directory header + if (!$this->_addFile($v_filename, $v_header, $p_add_dir, $p_remove_dir)) + return false; + + if (@is_dir($v_filename)) { + if (!($p_hdir = opendir($v_filename))) { + $this->_warning("Directory '$v_filename' can not be read"); + continue; + } + $p_hitem = readdir($p_hdir); // '.' directory + $p_hitem = readdir($p_hdir); // '..' directory + while (false !== ($p_hitem = readdir($p_hdir))) { + if ($v_filename != ".") + $p_temp_list[0] = $v_filename.'/'.$p_hitem; + else + $p_temp_list[0] = $p_hitem; + + $v_result = $this->_addList($p_temp_list, $p_add_dir, $p_remove_dir); + } + + unset($p_temp_list); + unset($p_hdir); + unset($p_hitem); + } + } + + return $v_result; + } + // }}} + + // {{{ _addFile() + function _addFile($p_filename, &$p_header, $p_add_dir, $p_remove_dir) + { + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if ($p_filename == '') { + $this->_error('Invalid file name'); + return false; + } + + // ----- Calculate the stored filename + $p_filename = $this->_translateWinPath($p_filename, false);; + $v_stored_filename = $p_filename; + if (strcmp($p_filename, $p_remove_dir) == 0) { + return true; + } + if ($p_remove_dir != '') { + if (substr($p_remove_dir, -1) != '/') + $p_remove_dir .= '/'; + + if (substr($p_filename, 0, strlen($p_remove_dir)) == $p_remove_dir) + $v_stored_filename = substr($p_filename, strlen($p_remove_dir)); + } + $v_stored_filename = $this->_translateWinPath($v_stored_filename); + if ($p_add_dir != '') { + if (substr($p_add_dir, -1) == '/') + $v_stored_filename = $p_add_dir.$v_stored_filename; + else + $v_stored_filename = $p_add_dir.'/'.$v_stored_filename; + } + + $v_stored_filename = $this->_pathReduction($v_stored_filename); + + if (is_file($p_filename)) { + if (($v_file = @fopen($p_filename, "rb")) == 0) { + $this->_warning("Unable to open file '$p_filename' in binary read mode"); + return true; + } + + if (!$this->_writeHeader($p_filename, $v_stored_filename)) + return false; + + while (($v_buffer = fread($v_file, 512)) != '') { + $v_binary_data = pack("a512", "$v_buffer"); + $this->_writeBlock($v_binary_data); + } + + fclose($v_file); + + } else { + // ----- Only header for dir + if (!$this->_writeHeader($p_filename, $v_stored_filename)) + return false; + } + + return true; + } + // }}} + + // {{{ _addString() + function _addString($p_filename, $p_string) + { + if (!$this->_file) { + $this->_error('Invalid file descriptor'); + return false; + } + + if ($p_filename == '') { + $this->_error('Invalid file name'); + return false; + } + + // ----- Calculate the stored filename + $p_filename = $this->_translateWinPath($p_filename, false);; + + if (!$this->_writeHeaderBlock($p_filename, strlen($p_string), 0, 0, "", 0, 0)) + return false; + + $i=0; + while (($v_buffer = substr($p_string, (($i++)*512), 512)) != '') { + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + } + + return true; + } + // }}} + + // {{{ _writeHeader() + function _writeHeader($p_filename, $p_stored_filename) + { + if ($p_stored_filename == '') + $p_stored_filename = $p_filename; + $v_reduce_filename = $this->_pathReduction($p_stored_filename); + + if (strlen($v_reduce_filename) > 99) { + if (!$this->_writeLongHeader($v_reduce_filename)) + return false; + } + + $v_info = stat($p_filename); + $v_uid = sprintf("%6s ", DecOct($v_info[4])); + $v_gid = sprintf("%6s ", DecOct($v_info[5])); + $v_perms = sprintf("%6s ", DecOct(fileperms($p_filename))); + + $v_mtime = sprintf("%11s", DecOct(filemtime($p_filename))); + + if (@is_dir($p_filename)) { + $v_typeflag = "5"; + $v_size = sprintf("%11s ", DecOct(0)); + } else { + $v_typeflag = ''; + clearstatcache(); + $v_size = sprintf("%11s ", DecOct(filesize($p_filename))); + } + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", $v_reduce_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + return true; + } + // }}} + + // {{{ _writeHeaderBlock() + function _writeHeaderBlock($p_filename, $p_size, $p_mtime=0, $p_perms=0, $p_type='', $p_uid=0, $p_gid=0) + { + $p_filename = $this->_pathReduction($p_filename); + + if (strlen($p_filename) > 99) { + if (!$this->_writeLongHeader($p_filename)) + return false; + } + + if ($p_type == "5") { + $v_size = sprintf("%11s ", DecOct(0)); + } else { + $v_size = sprintf("%11s ", DecOct($p_size)); + } + + $v_uid = sprintf("%6s ", DecOct($p_uid)); + $v_gid = sprintf("%6s ", DecOct($p_gid)); + $v_perms = sprintf("%6s ", DecOct($p_perms)); + + $v_mtime = sprintf("%11s", DecOct($p_mtime)); + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", $p_filename, $v_perms, $v_uid, $v_gid, $v_size, $v_mtime); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $p_type, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + return true; + } + // }}} + + // {{{ _writeLongHeader() + function _writeLongHeader($p_filename) + { + $v_size = sprintf("%11s ", DecOct(strlen($p_filename))); + + $v_typeflag = 'L'; + + $v_linkname = ''; + + $v_magic = ''; + + $v_version = ''; + + $v_uname = ''; + + $v_gname = ''; + + $v_devmajor = ''; + + $v_devminor = ''; + + $v_prefix = ''; + + $v_binary_data_first = pack("a100a8a8a8a12A12", '././@LongLink', 0, 0, 0, $v_size, 0); + $v_binary_data_last = pack("a1a100a6a2a32a32a8a8a155a12", $v_typeflag, $v_linkname, $v_magic, $v_version, $v_uname, $v_gname, $v_devmajor, $v_devminor, $v_prefix, ''); + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum += ord(substr($v_binary_data_first,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156, $j=0; $i<512; $i++, $j++) + $v_checksum += ord(substr($v_binary_data_last,$j,1)); + + // ----- Write the first 148 bytes of the header in the archive + $this->_writeBlock($v_binary_data_first, 148); + + // ----- Write the calculated checksum + $v_checksum = sprintf("%6s ", DecOct($v_checksum)); + $v_binary_data = pack("a8", $v_checksum); + $this->_writeBlock($v_binary_data, 8); + + // ----- Write the last 356 bytes of the header in the archive + $this->_writeBlock($v_binary_data_last, 356); + + // ----- Write the filename as content of the block + $i=0; + while (($v_buffer = substr($p_filename, (($i++)*512), 512)) != '') { + $v_binary_data = pack("a512", "$v_buffer"); + $this->_writeBlock($v_binary_data); + } + + return true; + } + // }}} + + // {{{ _readHeader() + function _readHeader($v_binary_data, &$v_header) + { + if (strlen($v_binary_data)==0) { + $v_header['filename'] = ''; + return true; + } + + if (strlen($v_binary_data) != 512) { + $v_header['filename'] = ''; + $this->_error('Invalid block size : '.strlen($v_binary_data)); + return false; + } + + // ----- Calculate the checksum + $v_checksum = 0; + // ..... First part of the header + for ($i=0; $i<148; $i++) + $v_checksum+=ord(substr($v_binary_data,$i,1)); + // ..... Ignore the checksum value and replace it by ' ' (space) + for ($i=148; $i<156; $i++) + $v_checksum += ord(' '); + // ..... Last part of the header + for ($i=156; $i<512; $i++) + $v_checksum+=ord(substr($v_binary_data,$i,1)); + + $v_data = unpack("a100filename/a8mode/a8uid/a8gid/a12size/a12mtime/a8checksum/a1typeflag/a100link/a6magic/a2version/a32uname/a32gname/a8devmajor/a8devminor", $v_binary_data); + + // ----- Extract the checksum + $v_header['checksum'] = OctDec(trim($v_data['checksum'])); + if ($v_header['checksum'] != $v_checksum) { + $v_header['filename'] = ''; + + // ----- Look for last block (empty block) + if (($v_checksum == 256) && ($v_header['checksum'] == 0)) + return true; + + $this->_error('Invalid checksum for file "'.$v_data['filename'].'" : '.$v_checksum.' calculated, '.$v_header['checksum'].' expected'); + return false; + } + + // ----- Extract the properties + $v_header['filename'] = trim($v_data['filename']); + $v_header['mode'] = OctDec(trim($v_data['mode'])); + $v_header['uid'] = OctDec(trim($v_data['uid'])); + $v_header['gid'] = OctDec(trim($v_data['gid'])); + $v_header['size'] = OctDec(trim($v_data['size'])); + $v_header['mtime'] = OctDec(trim($v_data['mtime'])); + if (($v_header['typeflag'] = $v_data['typeflag']) == "5") { + $v_header['size'] = 0; + } + /* ----- All these fields are removed form the header because they do not carry interesting info + $v_header[link] = trim($v_data[link]); + $v_header[magic] = trim($v_data[magic]); + $v_header[version] = trim($v_data[version]); + $v_header[uname] = trim($v_data[uname]); + $v_header[gname] = trim($v_data[gname]); + $v_header[devmajor] = trim($v_data[devmajor]); + $v_header[devminor] = trim($v_data[devminor]); + */ + + return true; + } + // }}} + + // {{{ _readLongHeader() + function _readLongHeader(&$v_header) + { + $v_filename = ''; + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_content = $this->_readBlock(); + $v_filename .= $v_content; + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + $v_filename .= $v_content; + } + + // ----- Read the next header + $v_binary_data = $this->_readBlock(); + + if (!$this->_readHeader($v_binary_data, $v_header)) + return false; + + $v_header['filename'] = $v_filename; + + return true; + } + // }}} + + // {{{ _extractInString() + /** + * This method extract from the archive one file identified by $p_filename. + * The return value is a string with the file content, or NULL on error. + * @param string $p_filename The path of the file to extract in a string. + * @return a string with the file content or NULL. + * @access private + */ + function _extractInString($p_filename) + { + $v_result_str = ""; + + While (strlen($v_binary_data = $this->_readBlock()) != 0) + { + if (!$this->_readHeader($v_binary_data, $v_header)) + return NULL; + + if ($v_header['filename'] == '') + continue; + + // ----- Look for long filename + if ($v_header['typeflag'] == 'L') { + if (!$this->_readLongHeader($v_header)) + return NULL; + } + + if ($v_header['filename'] == $p_filename) { + if ($v_header['typeflag'] == "5") { + $this->_error('Unable to extract in string a directory entry {'.$v_header['filename'].'}'); + return NULL; + } else { + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_result_str .= $this->_readBlock(); + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + $v_result_str .= substr($v_content, 0, ($v_header['size'] % 512)); + } + return $v_result_str; + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + } + + return NULL; + } + // }}} + + // {{{ _extractList() + function _extractList($p_path, &$p_list_detail, $p_mode, $p_file_list, $p_remove_path) + { + $v_result=true; + $v_nb = 0; + $v_extract_all = true; + $v_listing = false; + + $p_path = $this->_translateWinPath($p_path, false); + if ($p_path == '' || (substr($p_path, 0, 1) != '/' && substr($p_path, 0, 3) != "../" && !strpos($p_path, ':'))) { + $p_path = "./".$p_path; + } + $p_remove_path = $this->_translateWinPath($p_remove_path); + + // ----- Look for path to remove format (should end by /) + if (($p_remove_path != '') && (substr($p_remove_path, -1) != '/')) + $p_remove_path .= '/'; + $p_remove_path_size = strlen($p_remove_path); + + switch ($p_mode) { + case "complete" : + $v_extract_all = TRUE; + $v_listing = FALSE; + break; + case "partial" : + $v_extract_all = FALSE; + $v_listing = FALSE; + break; + case "list" : + $v_extract_all = FALSE; + $v_listing = TRUE; + break; + default : + $this->_error('Invalid extract mode ('.$p_mode.')'); + return false; + } + + clearstatcache(); + + While (strlen($v_binary_data = $this->_readBlock()) != 0) + { + $v_extract_file = FALSE; + $v_extraction_stopped = 0; + + if (!$this->_readHeader($v_binary_data, $v_header)) + return false; + + if ($v_header['filename'] == '') + continue; + + // ----- Look for long filename + if ($v_header['typeflag'] == 'L') { + if (!$this->_readLongHeader($v_header)) + return false; + } + + if ((!$v_extract_all) && (is_array($p_file_list))) { + // ----- By default no unzip if the file is not found + $v_extract_file = false; + + for ($i=0; $i strlen($p_file_list[$i])) && (substr($v_header['filename'], 0, strlen($p_file_list[$i])) == $p_file_list[$i])) { + $v_extract_file = TRUE; + break; + } + } + + // ----- It is a file, so compare the file names + elseif ($p_file_list[$i] == $v_header['filename']) { + $v_extract_file = TRUE; + break; + } + } + } else { + $v_extract_file = TRUE; + } + + // ----- Look if this file need to be extracted + if (($v_extract_file) && (!$v_listing)) + { + if (($p_remove_path != '') + && (substr($v_header['filename'], 0, $p_remove_path_size) == $p_remove_path)) + $v_header['filename'] = substr($v_header['filename'], $p_remove_path_size); + if (($p_path != './') && ($p_path != '/')) { + while (substr($p_path, -1) == '/') + $p_path = substr($p_path, 0, strlen($p_path)-1); + + if (substr($v_header['filename'], 0, 1) == '/') + $v_header['filename'] = $p_path.$v_header['filename']; + else + $v_header['filename'] = $p_path.'/'.$v_header['filename']; + } + if (file_exists($v_header['filename'])) { + if ((@is_dir($v_header['filename'])) && ($v_header['typeflag'] == '')) { + $this->_error('File '.$v_header['filename'].' already exists as a directory'); + return false; + } + if ((is_file($v_header['filename'])) && ($v_header['typeflag'] == "5")) { + $this->_error('Directory '.$v_header['filename'].' already exists as a file'); + return false; + } + if (!is_writeable($v_header['filename'])) { + $this->_error('File '.$v_header['filename'].' already exists and is write protected'); + return false; + } + if (filemtime($v_header['filename']) > $v_header['mtime']) { + // To be completed : An error or silent no replace ? + } + } + + // ----- Check the directory availability and create it if necessary + elseif (($v_result = $this->_dirCheck(($v_header['typeflag'] == "5"?$v_header['filename']:dirname($v_header['filename'])))) != 1) { + $this->_error('Unable to create path for '.$v_header['filename']); + return false; + } + + if ($v_extract_file) { + if ($v_header['typeflag'] == "5") { + if (!@file_exists($v_header['filename'])) { + if (!@mkdir($v_header['filename'], 0777)) { + $this->_error('Unable to create directory {'.$v_header['filename'].'}'); + return false; + } + } + } else { + if (($v_dest_file = @fopen($v_header['filename'], "wb")) == 0) { + $this->_error('Error while opening {'.$v_header['filename'].'} in write binary mode'); + return false; + } else { + $n = floor($v_header['size']/512); + for ($i=0; $i<$n; $i++) { + $v_content = $this->_readBlock(); + fwrite($v_dest_file, $v_content, 512); + } + if (($v_header['size'] % 512) != 0) { + $v_content = $this->_readBlock(); + fwrite($v_dest_file, $v_content, ($v_header['size'] % 512)); + } + + @fclose($v_dest_file); + + // ----- Change the file mode, mtime + @touch($v_header['filename'], $v_header['mtime']); + if ($v_header['mode'] & 0111) { + // make file executable, obey umask + $mode = fileperms($v_header['filename']) | (~umask() & 0111); + @chmod($v_header['filename'], $mode); + } + } + + // ----- Check the file size + clearstatcache(); + if (filesize($v_header['filename']) != $v_header['size']) { + $this->_error('Extracted file '.$v_header['filename'].' does not have the correct file size \''.filesize($v_filename).'\' ('.$v_header['size'].' expected). Archive may be corrupted.'); + return false; + } + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + } else { + $this->_jumpBlock(ceil(($v_header['size']/512))); + } + + /* TBC : Seems to be unused ... + if ($this->_compress) + $v_end_of_file = @gzeof($this->_file); + else + $v_end_of_file = @feof($this->_file); + */ + + if ($v_listing || $v_extract_file || $v_extraction_stopped) { + // ----- Log extracted files + if (($v_file_dir = dirname($v_header['filename'])) == $v_header['filename']) + $v_file_dir = ''; + if ((substr($v_header['filename'], 0, 1) == '/') && ($v_file_dir == '')) + $v_file_dir = '/'; + + $p_list_detail[$v_nb++] = $v_header; + } + } + + return true; + } + // }}} + + // {{{ _openAppend() + function _openAppend() + { + if (filesize($this->_tarname) == 0) + return $this->_openWrite(); + + if ($this->_compress) { + $this->_close(); + + if (!@rename($this->_tarname, $this->_tarname.".tmp")) { + $this->_error('Error while renaming \''.$this->_tarname.'\' to temporary file \''.$this->_tarname.'.tmp\''); + return false; + } + + if ($this->_compress_type == 'gz') + $v_temp_tar = @gzopen($this->_tarname.".tmp", "rb"); + elseif ($this->_compress_type == 'bz2') + $v_temp_tar = @bzopen($this->_tarname.".tmp", "rb"); + + if ($v_temp_tar == 0) { + $this->_error('Unable to open file \''.$this->_tarname.'.tmp\' in binary read mode'); + @rename($this->_tarname.".tmp", $this->_tarname); + return false; + } + + if (!$this->_openWrite()) { + @rename($this->_tarname.".tmp", $this->_tarname); + return false; + } + + if ($this->_compress_type == 'gz') { + $v_buffer = @gzread($v_temp_tar, 512); + + // ----- Read the following blocks but not the last one + if (!@gzeof($v_temp_tar)) { + do{ + $v_binary_data = pack("a512", $v_buffer); + $this->_writeBlock($v_binary_data); + $v_buffer = @gzread($v_temp_tar, 512); + + } while (!@gzeof($v_temp_tar)); + } + + @gzclose($v_temp_tar); + } + elseif ($this->_compress_type == 'bz2') { + $v_buffered_lines = array(); + $v_buffered_lines[] = @bzread($v_temp_tar, 512); + + // ----- Read the following blocks but not the last one + while (strlen($v_buffered_lines[] = @bzread($v_temp_tar, 512)) > 0) { + $v_binary_data = pack("a512", array_shift($v_buffered_lines)); + $this->_writeBlock($v_binary_data); + } + + @bzclose($v_temp_tar); + } + + if (!@unlink($this->_tarname.".tmp")) { + $this->_error('Error while deleting temporary file \''.$this->_tarname.'.tmp\''); + } + + } else { + // ----- For not compressed tar, just add files before the last 512 bytes block + if (!$this->_openReadWrite()) + return false; + + clearstatcache(); + $v_size = filesize($this->_tarname); + fseek($this->_file, $v_size-512); + } + + return true; + } + // }}} + + // {{{ _append() + function _append($p_filelist, $p_add_dir='', $p_remove_dir='') + { + if (!$this->_openAppend()) + return false; + + if ($this->_addList($p_filelist, $p_add_dir, $p_remove_dir)) + $this->_writeFooter(); + + $this->_close(); + + return true; + } + // }}} + + // {{{ _dirCheck() + + /** + * Check if a directory exists and create it (including parent + * dirs) if not. + * + * @param string $p_dir directory to check + * + * @return bool TRUE if the directory exists or was created + */ + function _dirCheck($p_dir) + { + if ((@is_dir($p_dir)) || ($p_dir == '')) + return true; + + $p_parent_dir = dirname($p_dir); + + if (($p_parent_dir != $p_dir) && + ($p_parent_dir != '') && + (!$this->_dirCheck($p_parent_dir))) + return false; + + if (!@mkdir($p_dir, 0777)) { + $this->_error("Unable to create directory '$p_dir'"); + return false; + } + + return true; + } + + // }}} + + // {{{ _pathReduction() + + /** + * Compress path by changing for example "/dir/foo/../bar" to "/dir/bar", and + * remove double slashes. + * + * @param string $p_dir path to reduce + * + * @return string reduced path + * + * @access private + * + */ + function _pathReduction($p_dir) + { + $v_result = ''; + + // ----- Look for not empty path + if ($p_dir != '') { + // ----- Explode path by directory names + $v_list = explode('/', $p_dir); + + // ----- Study directories from last to first + for ($i=sizeof($v_list)-1; $i>=0; $i--) { + // ----- Look for current path + if ($v_list[$i] == ".") { + // ----- Ignore this directory + // Should be the first $i=0, but no check is done + } + else if ($v_list[$i] == "..") { + // ----- Ignore it and ignore the $i-1 + $i--; + } + else if (($v_list[$i] == '') && ($i!=(sizeof($v_list)-1)) && ($i!=0)) { + // ----- Ignore only the double '//' in path, + // but not the first and last / + } else { + $v_result = $v_list[$i].($i!=(sizeof($v_list)-1)?'/'.$v_result:''); + } + } + } + $v_result = strtr($v_result, '\\', '/'); + return $v_result; + } + + // }}} + + // {{{ _translateWinPath() + function _translateWinPath($p_path, $p_remove_disk_letter=true) + { + if (OS_WINDOWS) { + // ----- Look for potential disk letter + if (($p_remove_disk_letter) && (($v_position = strpos($p_path, ':')) != false)) { + $p_path = substr($p_path, $v_position+1); + } + // ----- Change potential windows directory separator + if ((strpos($p_path, '\\') > 0) || (substr($p_path, 0,1) == '\\')) { + $p_path = strtr($p_path, '\\', '/'); + } + } + return $p_path; + } + // }}} + +} +?> diff --git a/common/PEAR/Console/Getopt.php b/common/PEAR/Console/Getopt.php new file mode 100644 index 0000000..ac207c5 --- /dev/null +++ b/common/PEAR/Console/Getopt.php @@ -0,0 +1,251 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Getopt.php,v 1.21.4.8 2003/12/11 19:28:25 andrei Exp $ + +require_once 'PEAR.php'; + +/** + * Command-line options parsing class. + * + * @author Andrei Zmievski + * + */ +class Console_Getopt { + /** + * Parses the command-line options. + * + * The first parameter to this function should be the list of command-line + * arguments without the leading reference to the running program. + * + * The second parameter is a string of allowed short options. Each of the + * option letters can be followed by a colon ':' to specify that the option + * requires an argument, or a double colon '::' to specify that the option + * takes an optional argument. + * + * The third argument is an optional array of allowed long options. The + * leading '--' should not be included in the option name. Options that + * require an argument should be followed by '=', and options that take an + * option argument should be followed by '=='. + * + * The return value is an array of two elements: the list of parsed + * options and the list of non-option command-line arguments. Each entry in + * the list of parsed options is a pair of elements - the first one + * specifies the option, and the second one specifies the option argument, + * if there was one. + * + * Long and short options can be mixed. + * + * Most of the semantics of this function are based on GNU getopt_long(). + * + * @param array $args an array of command-line arguments + * @param string $short_options specifies the list of allowed short options + * @param array $long_options specifies the list of allowed long options + * + * @return array two-element array containing the list of parsed options and + * the non-option arguments + * + * @access public + * + */ + function getopt2($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(2, $args, $short_options, $long_options); + } + + /** + * This function expects $args to start with the script name (POSIX-style). + * Preserved for backwards compatibility. + * @see getopt2() + */ + function getopt($args, $short_options, $long_options = null) + { + return Console_Getopt::doGetopt(1, $args, $short_options, $long_options); + } + + /** + * The actual implementation of the argument parsing code. + */ + function doGetopt($version, $args, $short_options, $long_options = null) + { + // in case you pass directly readPHPArgv() as the first arg + if (PEAR::isError($args)) { + return $args; + } + if (empty($args)) { + return array(array(), array()); + } + $opts = array(); + $non_opts = array(); + + settype($args, 'array'); + + if ($long_options) { + sort($long_options); + } + + /* + * Preserve backwards compatibility with callers that relied on + * erroneous POSIX fix. + */ + if ($version < 2) { + if (isset($args[0]{0}) && $args[0]{0} != '-') { + array_shift($args); + } + } + + reset($args); + while (list($i, $arg) = each($args)) { + + /* The special element '--' means explicit end of + options. Treat the rest of the arguments as non-options + and end the loop. */ + if ($arg == '--') { + $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); + break; + } + + if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) { + $non_opts = array_merge($non_opts, array_slice($args, $i)); + break; + } elseif (strlen($arg) > 1 && $arg{1} == '-') { + $error = Console_Getopt::_parseLongOption(substr($arg, 2), $long_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } else { + $error = Console_Getopt::_parseShortOption(substr($arg, 1), $short_options, $opts, $args); + if (PEAR::isError($error)) + return $error; + } + } + + return array($opts, $non_opts); + } + + /** + * @access private + * + */ + function _parseShortOption($arg, $short_options, &$opts, &$args) + { + for ($i = 0; $i < strlen($arg); $i++) { + $opt = $arg{$i}; + $opt_arg = null; + + /* Try to find the short option in the specifier string. */ + if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') + { + return PEAR::raiseError("Console_Getopt: unrecognized option -- $opt"); + } + + if (strlen($spec) > 1 && $spec{1} == ':') { + if (strlen($spec) > 2 && $spec{2} == ':') { + if ($i + 1 < strlen($arg)) { + /* Option takes an optional argument. Use the remainder of + the arg string if there is anything left. */ + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } + } else { + /* Option requires an argument. Use the remainder of the arg + string if there is anything left. */ + if ($i + 1 < strlen($arg)) { + $opts[] = array($opt, substr($arg, $i + 1)); + break; + } else if (list(, $opt_arg) = each($args)) + /* Else use the next argument. */; + else + return PEAR::raiseError("Console_Getopt: option requires an argument -- $opt"); + } + } + + $opts[] = array($opt, $opt_arg); + } + } + + /** + * @access private + * + */ + function _parseLongOption($arg, $long_options, &$opts, &$args) + { + @list($opt, $opt_arg) = explode('=', $arg); + $opt_len = strlen($opt); + + for ($i = 0; $i < count($long_options); $i++) { + $long_opt = $long_options[$i]; + $opt_start = substr($long_opt, 0, $opt_len); + + /* Option doesn't match. Go on to the next one. */ + if ($opt_start != $opt) + continue; + + $opt_rest = substr($long_opt, $opt_len); + + /* Check that the options uniquely matches one of the allowed + options. */ + if ($opt_rest != '' && $opt{0} != '=' && + $i + 1 < count($long_options) && + $opt == substr($long_options[$i+1], 0, $opt_len)) { + return PEAR::raiseError("Console_Getopt: option --$opt is ambiguous"); + } + + if (substr($long_opt, -1) == '=') { + if (substr($long_opt, -2) != '==') { + /* Long option requires an argument. + Take the next argument if one wasn't specified. */; + if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) { + return PEAR::raiseError("Console_Getopt: option --$opt requires an argument"); + } + } + } else if ($opt_arg) { + return PEAR::raiseError("Console_Getopt: option --$opt doesn't allow an argument"); + } + + $opts[] = array('--' . $opt, $opt_arg); + return; + } + + return PEAR::raiseError("Console_Getopt: unrecognized option --$opt"); + } + + /** + * Safely read the $argv PHP array across different PHP configurations. + * Will take care on register_globals and register_argc_argv ini directives + * + * @access public + * @return mixed the $argv PHP array or PEAR error if not registered + */ + function readPHPArgv() + { + global $argv; + if (!is_array($argv)) { + if (!@is_array($_SERVER['argv'])) { + if (!@is_array($GLOBALS['HTTP_SERVER_VARS']['argv'])) { + return PEAR::raiseError("Console_Getopt: Could not read cmd args (register_argc_argv=Off?)"); + } + return $GLOBALS['HTTP_SERVER_VARS']['argv']; + } + return $_SERVER['argv']; + } + return $argv; + } + +} + +?> diff --git a/common/PEAR/DB.php b/common/PEAR/DB.php new file mode 100644 index 0000000..d24be9b --- /dev/null +++ b/common/PEAR/DB.php @@ -0,0 +1,1489 @@ + + * @author Tomas V.V.Cox + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: DB.php,v 1.88 2007/08/12 05:27:25 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the PEAR class so it can be extended from + */ +require_once 'PEAR.php'; + + +// {{{ constants +// {{{ error codes + +/**#@+ + * One of PEAR DB's portable error codes. + * @see DB_common::errorCode(), DB::errorMessage() + * + * {@internal If you add an error code here, make sure you also add a textual + * version of it in DB::errorMessage().}} + */ + +/** + * The code returned by many methods upon success + */ +define('DB_OK', 1); + +/** + * Unkown error + */ +define('DB_ERROR', -1); + +/** + * Syntax error + */ +define('DB_ERROR_SYNTAX', -2); + +/** + * Tried to insert a duplicate value into a primary or unique index + */ +define('DB_ERROR_CONSTRAINT', -3); + +/** + * An identifier in the query refers to a non-existant object + */ +define('DB_ERROR_NOT_FOUND', -4); + +/** + * Tried to create a duplicate object + */ +define('DB_ERROR_ALREADY_EXISTS', -5); + +/** + * The current driver does not support the action you attempted + */ +define('DB_ERROR_UNSUPPORTED', -6); + +/** + * The number of parameters does not match the number of placeholders + */ +define('DB_ERROR_MISMATCH', -7); + +/** + * A literal submitted did not match the data type expected + */ +define('DB_ERROR_INVALID', -8); + +/** + * The current DBMS does not support the action you attempted + */ +define('DB_ERROR_NOT_CAPABLE', -9); + +/** + * A literal submitted was too long so the end of it was removed + */ +define('DB_ERROR_TRUNCATED', -10); + +/** + * A literal number submitted did not match the data type expected + */ +define('DB_ERROR_INVALID_NUMBER', -11); + +/** + * A literal date submitted did not match the data type expected + */ +define('DB_ERROR_INVALID_DATE', -12); + +/** + * Attempt to divide something by zero + */ +define('DB_ERROR_DIVZERO', -13); + +/** + * A database needs to be selected + */ +define('DB_ERROR_NODBSELECTED', -14); + +/** + * Could not create the object requested + */ +define('DB_ERROR_CANNOT_CREATE', -15); + +/** + * Could not drop the database requested because it does not exist + */ +define('DB_ERROR_CANNOT_DROP', -17); + +/** + * An identifier in the query refers to a non-existant table + */ +define('DB_ERROR_NOSUCHTABLE', -18); + +/** + * An identifier in the query refers to a non-existant column + */ +define('DB_ERROR_NOSUCHFIELD', -19); + +/** + * The data submitted to the method was inappropriate + */ +define('DB_ERROR_NEED_MORE_DATA', -20); + +/** + * The attempt to lock the table failed + */ +define('DB_ERROR_NOT_LOCKED', -21); + +/** + * The number of columns doesn't match the number of values + */ +define('DB_ERROR_VALUE_COUNT_ON_ROW', -22); + +/** + * The DSN submitted has problems + */ +define('DB_ERROR_INVALID_DSN', -23); + +/** + * Could not connect to the database + */ +define('DB_ERROR_CONNECT_FAILED', -24); + +/** + * The PHP extension needed for this DBMS could not be found + */ +define('DB_ERROR_EXTENSION_NOT_FOUND',-25); + +/** + * The present user has inadequate permissions to perform the task requestd + */ +define('DB_ERROR_ACCESS_VIOLATION', -26); + +/** + * The database requested does not exist + */ +define('DB_ERROR_NOSUCHDB', -27); + +/** + * Tried to insert a null value into a column that doesn't allow nulls + */ +define('DB_ERROR_CONSTRAINT_NOT_NULL',-29); +/**#@-*/ + + +// }}} +// {{{ prepared statement-related + + +/**#@+ + * Identifiers for the placeholders used in prepared statements. + * @see DB_common::prepare() + */ + +/** + * Indicates a scalar (?) placeholder was used + * + * Quote and escape the value as necessary. + */ +define('DB_PARAM_SCALAR', 1); + +/** + * Indicates an opaque (&) placeholder was used + * + * The value presented is a file name. Extract the contents of that file + * and place them in this column. + */ +define('DB_PARAM_OPAQUE', 2); + +/** + * Indicates a misc (!) placeholder was used + * + * The value should not be quoted or escaped. + */ +define('DB_PARAM_MISC', 3); +/**#@-*/ + + +// }}} +// {{{ binary data-related + + +/**#@+ + * The different ways of returning binary data from queries. + */ + +/** + * Sends the fetched data straight through to output + */ +define('DB_BINMODE_PASSTHRU', 1); + +/** + * Lets you return data as usual + */ +define('DB_BINMODE_RETURN', 2); + +/** + * Converts the data to hex format before returning it + * + * For example the string "123" would become "313233". + */ +define('DB_BINMODE_CONVERT', 3); +/**#@-*/ + + +// }}} +// {{{ fetch modes + + +/**#@+ + * Fetch Modes. + * @see DB_common::setFetchMode() + */ + +/** + * Indicates the current default fetch mode should be used + * @see DB_common::$fetchmode + */ +define('DB_FETCHMODE_DEFAULT', 0); + +/** + * Column data indexed by numbers, ordered from 0 and up + */ +define('DB_FETCHMODE_ORDERED', 1); + +/** + * Column data indexed by column names + */ +define('DB_FETCHMODE_ASSOC', 2); + +/** + * Column data as object properties + */ +define('DB_FETCHMODE_OBJECT', 3); + +/** + * For multi-dimensional results, make the column name the first level + * of the array and put the row number in the second level of the array + * + * This is flipped from the normal behavior, which puts the row numbers + * in the first level of the array and the column names in the second level. + */ +define('DB_FETCHMODE_FLIPPED', 4); +/**#@-*/ + +/**#@+ + * Old fetch modes. Left here for compatibility. + */ +define('DB_GETMODE_ORDERED', DB_FETCHMODE_ORDERED); +define('DB_GETMODE_ASSOC', DB_FETCHMODE_ASSOC); +define('DB_GETMODE_FLIPPED', DB_FETCHMODE_FLIPPED); +/**#@-*/ + + +// }}} +// {{{ tableInfo() && autoPrepare()-related + + +/**#@+ + * The type of information to return from the tableInfo() method. + * + * Bitwised constants, so they can be combined using | + * and removed using ^. + * + * @see DB_common::tableInfo() + * + * {@internal Since the TABLEINFO constants are bitwised, if more of them are + * added in the future, make sure to adjust DB_TABLEINFO_FULL accordingly.}} + */ +define('DB_TABLEINFO_ORDER', 1); +define('DB_TABLEINFO_ORDERTABLE', 2); +define('DB_TABLEINFO_FULL', 3); +/**#@-*/ + + +/**#@+ + * The type of query to create with the automatic query building methods. + * @see DB_common::autoPrepare(), DB_common::autoExecute() + */ +define('DB_AUTOQUERY_INSERT', 1); +define('DB_AUTOQUERY_UPDATE', 2); +/**#@-*/ + + +// }}} +// {{{ portability modes + + +/**#@+ + * Portability Modes. + * + * Bitwised constants, so they can be combined using | + * and removed using ^. + * + * @see DB_common::setOption() + * + * {@internal Since the PORTABILITY constants are bitwised, if more of them are + * added in the future, make sure to adjust DB_PORTABILITY_ALL accordingly.}} + */ + +/** + * Turn off all portability features + */ +define('DB_PORTABILITY_NONE', 0); + +/** + * Convert names of tables and fields to lower case + * when using the get*(), fetch*() and tableInfo() methods + */ +define('DB_PORTABILITY_LOWERCASE', 1); + +/** + * Right trim the data output by get*() and fetch*() + */ +define('DB_PORTABILITY_RTRIM', 2); + +/** + * Force reporting the number of rows deleted + */ +define('DB_PORTABILITY_DELETE_COUNT', 4); + +/** + * Enable hack that makes numRows() work in Oracle + */ +define('DB_PORTABILITY_NUMROWS', 8); + +/** + * Makes certain error messages in certain drivers compatible + * with those from other DBMS's + * + * + mysql, mysqli: change unique/primary key constraints + * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT + * + * + odbc(access): MS's ODBC driver reports 'no such field' as code + * 07001, which means 'too few parameters.' When this option is on + * that code gets mapped to DB_ERROR_NOSUCHFIELD. + */ +define('DB_PORTABILITY_ERRORS', 16); + +/** + * Convert null values to empty strings in data output by + * get*() and fetch*() + */ +define('DB_PORTABILITY_NULL_TO_EMPTY', 32); + +/** + * Turn on all portability features + */ +define('DB_PORTABILITY_ALL', 63); +/**#@-*/ + +// }}} + + +// }}} +// {{{ class DB + +/** + * Database independent query interface + * + * The main "DB" class is simply a container class with some static + * methods for creating DB objects as well as some utility functions + * common to all parts of DB. + * + * The object model of DB is as follows (indentation means inheritance): + *
+ * DB           The main DB class.  This is simply a utility class
+ *              with some "static" methods for creating DB objects as
+ *              well as common utility functions for other DB classes.
+ *
+ * DB_common    The base for each DB implementation.  Provides default
+ * |            implementations (in OO lingo virtual methods) for
+ * |            the actual DB implementations as well as a bunch of
+ * |            query utility functions.
+ * |
+ * +-DB_mysql   The DB implementation for MySQL.  Inherits DB_common.
+ *              When calling DB::factory or DB::connect for MySQL
+ *              connections, the object returned is an instance of this
+ *              class.
+ * 
+ * + * @category Database + * @package DB + * @author Stig Bakken + * @author Tomas V.V.Cox + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB +{ + // {{{ &factory() + + /** + * Create a new DB object for the specified database type but don't + * connect to the database + * + * @param string $type the database type (eg "mysql") + * @param array $options an associative array of option names and values + * + * @return object a new DB object. A DB_Error object on failure. + * + * @see DB_common::setOption() + */ + function &factory($type, $options = false) + { + if (!is_array($options)) { + $options = array('persistent' => $options); + } + + if (isset($options['debug']) && $options['debug'] >= 2) { + // expose php errors with sufficient debug level + include_once "DB/{$type}.php"; + } else { + @include_once "DB/{$type}.php"; + } + + $classname = "DB_${type}"; + + if (!class_exists($classname)) { + $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, + "Unable to include the DB/{$type}.php" + . " file for '$dsn'", + 'DB_Error', true); + return $tmp; + } + + @$obj = new $classname; + + foreach ($options as $option => $value) { + $test = $obj->setOption($option, $value); + if (DB::isError($test)) { + return $test; + } + } + + return $obj; + } + + // }}} + // {{{ &connect() + + /** + * Create a new DB object including a connection to the specified database + * + * Example 1. + * + * require_once 'DB.php'; + * + * $dsn = 'pgsql://user:password@host/database'; + * $options = array( + * 'debug' => 2, + * 'portability' => DB_PORTABILITY_ALL, + * ); + * + * $db =& DB::connect($dsn, $options); + * if (PEAR::isError($db)) { + * die($db->getMessage()); + * } + * + * + * @param mixed $dsn the string "data source name" or array in the + * format returned by DB::parseDSN() + * @param array $options an associative array of option names and values + * + * @return object a new DB object. A DB_Error object on failure. + * + * @uses DB_dbase::connect(), DB_fbsql::connect(), DB_ibase::connect(), + * DB_ifx::connect(), DB_msql::connect(), DB_mssql::connect(), + * DB_mysql::connect(), DB_mysqli::connect(), DB_oci8::connect(), + * DB_odbc::connect(), DB_pgsql::connect(), DB_sqlite::connect(), + * DB_sybase::connect() + * + * @uses DB::parseDSN(), DB_common::setOption(), PEAR::isError() + */ + function &connect($dsn, $options = array()) + { + $dsninfo = DB::parseDSN($dsn); + $type = $dsninfo['phptype']; + + if (!is_array($options)) { + /* + * For backwards compatibility. $options used to be boolean, + * indicating whether the connection should be persistent. + */ + $options = array('persistent' => $options); + } + + if (isset($options['debug']) && $options['debug'] >= 2) { + // expose php errors with sufficient debug level + include_once "DB/${type}.php"; + } else { + @include_once "DB/${type}.php"; + } + + $classname = "DB_${type}"; + if (!class_exists($classname)) { + $tmp = PEAR::raiseError(null, DB_ERROR_NOT_FOUND, null, null, + "Unable to include the DB/{$type}.php" + . " file for '$dsn'", + 'DB_Error', true); + return $tmp; + } + + @$obj = new $classname; + + foreach ($options as $option => $value) { + $test = $obj->setOption($option, $value); + if (DB::isError($test)) { + return $test; + } + } + + $err = $obj->connect($dsninfo, $obj->getOption('persistent')); + if (DB::isError($err)) { + if (is_array($dsn)) { + $err->addUserInfo(DB::getDSNString($dsn, true)); + } else { + $err->addUserInfo($dsn); + } + return $err; + } + + return $obj; + } + + // }}} + // {{{ apiVersion() + + /** + * Return the DB API version + * + * @return string the DB API version number + */ + function apiVersion() + { + return '1.7.13'; + } + + // }}} + // {{{ isError() + + /** + * Determines if a variable is a DB_Error object + * + * @param mixed $value the variable to check + * + * @return bool whether $value is DB_Error object + */ + function isError($value) + { + return is_a($value, 'DB_Error'); + } + + // }}} + // {{{ isConnection() + + /** + * Determines if a value is a DB_ object + * + * @param mixed $value the value to test + * + * @return bool whether $value is a DB_ object + */ + function isConnection($value) + { + return (is_object($value) && + is_subclass_of($value, 'db_common') && + method_exists($value, 'simpleQuery')); + } + + // }}} + // {{{ isManip() + + /** + * Tell whether a query is a data manipulation or data definition query + * + * Examples of data manipulation queries are INSERT, UPDATE and DELETE. + * Examples of data definition queries are CREATE, DROP, ALTER, GRANT, + * REVOKE. + * + * @param string $query the query + * + * @return boolean whether $query is a data manipulation query + */ + function isManip($query) + { + $manips = 'INSERT|UPDATE|DELETE|REPLACE|' + . 'CREATE|DROP|' + . 'LOAD DATA|SELECT .* INTO .* FROM|COPY|' + . 'ALTER|GRANT|REVOKE|' + . 'LOCK|UNLOCK'; + if (preg_match('/^\s*"?(' . $manips . ')\s+/i', $query)) { + return true; + } + return false; + } + + // }}} + // {{{ errorMessage() + + /** + * Return a textual error message for a DB error code + * + * @param integer $value the DB error code + * + * @return string the error message or false if the error code was + * not recognized + */ + function errorMessage($value) + { + static $errorMessages; + if (!isset($errorMessages)) { + $errorMessages = array( + DB_ERROR => 'unknown error', + DB_ERROR_ACCESS_VIOLATION => 'insufficient permissions', + DB_ERROR_ALREADY_EXISTS => 'already exists', + DB_ERROR_CANNOT_CREATE => 'can not create', + DB_ERROR_CANNOT_DROP => 'can not drop', + DB_ERROR_CONNECT_FAILED => 'connect failed', + DB_ERROR_CONSTRAINT => 'constraint violation', + DB_ERROR_CONSTRAINT_NOT_NULL=> 'null value violates not-null constraint', + DB_ERROR_DIVZERO => 'division by zero', + DB_ERROR_EXTENSION_NOT_FOUND=> 'extension not found', + DB_ERROR_INVALID => 'invalid', + DB_ERROR_INVALID_DATE => 'invalid date or time', + DB_ERROR_INVALID_DSN => 'invalid DSN', + DB_ERROR_INVALID_NUMBER => 'invalid number', + DB_ERROR_MISMATCH => 'mismatch', + DB_ERROR_NEED_MORE_DATA => 'insufficient data supplied', + DB_ERROR_NODBSELECTED => 'no database selected', + DB_ERROR_NOSUCHDB => 'no such database', + DB_ERROR_NOSUCHFIELD => 'no such field', + DB_ERROR_NOSUCHTABLE => 'no such table', + DB_ERROR_NOT_CAPABLE => 'DB backend not capable', + DB_ERROR_NOT_FOUND => 'not found', + DB_ERROR_NOT_LOCKED => 'not locked', + DB_ERROR_SYNTAX => 'syntax error', + DB_ERROR_UNSUPPORTED => 'not supported', + DB_ERROR_TRUNCATED => 'truncated', + DB_ERROR_VALUE_COUNT_ON_ROW => 'value count on row', + DB_OK => 'no error', + ); + } + + if (DB::isError($value)) { + $value = $value->getCode(); + } + + return isset($errorMessages[$value]) ? $errorMessages[$value] + : $errorMessages[DB_ERROR]; + } + + // }}} + // {{{ parseDSN() + + /** + * Parse a data source name + * + * Additional keys can be added by appending a URI query string to the + * end of the DSN. + * + * The format of the supplied DSN is in its fullest form: + * + * phptype(dbsyntax)://username:password@protocol+hostspec/database?option=8&another=true + * + * + * Most variations are allowed: + * + * phptype://username:password@protocol+hostspec:110//usr/db_file.db?mode=0644 + * phptype://username:password@hostspec/database_name + * phptype://username:password@hostspec + * phptype://username@hostspec + * phptype://hostspec/database + * phptype://hostspec + * phptype(dbsyntax) + * phptype + * + * + * @param string $dsn Data Source Name to be parsed + * + * @return array an associative array with the following keys: + * + phptype: Database backend used in PHP (mysql, odbc etc.) + * + dbsyntax: Database used with regards to SQL syntax etc. + * + protocol: Communication protocol to use (tcp, unix etc.) + * + hostspec: Host specification (hostname[:port]) + * + database: Database to use on the DBMS server + * + username: User name for login + * + password: Password for login + */ + function parseDSN($dsn) + { + $parsed = array( + 'phptype' => false, + 'dbsyntax' => false, + 'username' => false, + 'password' => false, + 'protocol' => false, + 'hostspec' => false, + 'port' => false, + 'socket' => false, + 'database' => false, + ); + + if (is_array($dsn)) { + $dsn = array_merge($parsed, $dsn); + if (!$dsn['dbsyntax']) { + $dsn['dbsyntax'] = $dsn['phptype']; + } + return $dsn; + } + + // Find phptype and dbsyntax + if (($pos = strpos($dsn, '://')) !== false) { + $str = substr($dsn, 0, $pos); + $dsn = substr($dsn, $pos + 3); + } else { + $str = $dsn; + $dsn = null; + } + + // Get phptype and dbsyntax + // $str => phptype(dbsyntax) + if (preg_match('|^(.+?)\((.*?)\)$|', $str, $arr)) { + $parsed['phptype'] = $arr[1]; + $parsed['dbsyntax'] = !$arr[2] ? $arr[1] : $arr[2]; + } else { + $parsed['phptype'] = $str; + $parsed['dbsyntax'] = $str; + } + + if (!count($dsn)) { + return $parsed; + } + + // Get (if found): username and password + // $dsn => username:password@protocol+hostspec/database + if (($at = strrpos($dsn,'@')) !== false) { + $str = substr($dsn, 0, $at); + $dsn = substr($dsn, $at + 1); + if (($pos = strpos($str, ':')) !== false) { + $parsed['username'] = rawurldecode(substr($str, 0, $pos)); + $parsed['password'] = rawurldecode(substr($str, $pos + 1)); + } else { + $parsed['username'] = rawurldecode($str); + } + } + + // Find protocol and hostspec + + if (preg_match('|^([^(]+)\((.*?)\)/?(.*?)$|', $dsn, $match)) { + // $dsn => proto(proto_opts)/database + $proto = $match[1]; + $proto_opts = $match[2] ? $match[2] : false; + $dsn = $match[3]; + + } else { + // $dsn => protocol+hostspec/database (old format) + if (strpos($dsn, '+') !== false) { + list($proto, $dsn) = explode('+', $dsn, 2); + } + if (strpos($dsn, '/') !== false) { + list($proto_opts, $dsn) = explode('/', $dsn, 2); + } else { + $proto_opts = $dsn; + $dsn = null; + } + } + + // process the different protocol options + $parsed['protocol'] = (!empty($proto)) ? $proto : 'tcp'; + $proto_opts = rawurldecode($proto_opts); + if (strpos($proto_opts, ':') !== false) { + list($proto_opts, $parsed['port']) = explode(':', $proto_opts); + } + if ($parsed['protocol'] == 'tcp') { + $parsed['hostspec'] = $proto_opts; + } elseif ($parsed['protocol'] == 'unix') { + $parsed['socket'] = $proto_opts; + } + + // Get dabase if any + // $dsn => database + if ($dsn) { + if (($pos = strpos($dsn, '?')) === false) { + // /database + $parsed['database'] = rawurldecode($dsn); + } else { + // /database?param1=value1¶m2=value2 + $parsed['database'] = rawurldecode(substr($dsn, 0, $pos)); + $dsn = substr($dsn, $pos + 1); + if (strpos($dsn, '&') !== false) { + $opts = explode('&', $dsn); + } else { // database?param1=value1 + $opts = array($dsn); + } + foreach ($opts as $opt) { + list($key, $value) = explode('=', $opt); + if (!isset($parsed[$key])) { + // don't allow params overwrite + $parsed[$key] = rawurldecode($value); + } + } + } + } + + return $parsed; + } + + // }}} + // {{{ getDSNString() + + /** + * Returns the given DSN in a string format suitable for output. + * + * @param array|string the DSN to parse and format + * @param boolean true to hide the password, false to include it + * @return string + */ + function getDSNString($dsn, $hidePassword) { + /* Calling parseDSN will ensure that we have all the array elements + * defined, and means that we deal with strings and array in the same + * manner. */ + $dsnArray = DB::parseDSN($dsn); + + if ($hidePassword) { + $dsnArray['password'] = 'PASSWORD'; + } + + /* Protocol is special-cased, as using the default "tcp" along with an + * Oracle TNS connection string fails. */ + if (is_string($dsn) && strpos($dsn, 'tcp') === false && $dsnArray['protocol'] == 'tcp') { + $dsnArray['protocol'] = false; + } + + // Now we just have to construct the actual string. This is ugly. + $dsnString = $dsnArray['phptype']; + if ($dsnArray['dbsyntax']) { + $dsnString .= '('.$dsnArray['dbsyntax'].')'; + } + $dsnString .= '://' + .$dsnArray['username'] + .':' + .$dsnArray['password'] + .'@' + .$dsnArray['protocol']; + if ($dsnArray['socket']) { + $dsnString .= '('.$dsnArray['socket'].')'; + } + if ($dsnArray['protocol'] && $dsnArray['hostspec']) { + $dsnString .= '+'; + } + $dsnString .= $dsnArray['hostspec']; + if ($dsnArray['port']) { + $dsnString .= ':'.$dsnArray['port']; + } + $dsnString .= '/'.$dsnArray['database']; + + /* Option handling. Unfortunately, parseDSN simply places options into + * the top-level array, so we'll first get rid of the fields defined by + * DB and see what's left. */ + unset($dsnArray['phptype'], + $dsnArray['dbsyntax'], + $dsnArray['username'], + $dsnArray['password'], + $dsnArray['protocol'], + $dsnArray['socket'], + $dsnArray['hostspec'], + $dsnArray['port'], + $dsnArray['database'] + ); + if (count($dsnArray) > 0) { + $dsnString .= '?'; + $i = 0; + foreach ($dsnArray as $key => $value) { + if (++$i > 1) { + $dsnString .= '&'; + } + $dsnString .= $key.'='.$value; + } + } + + return $dsnString; + } + + // }}} +} + +// }}} +// {{{ class DB_Error + +/** + * DB_Error implements a class for reporting portable database error + * messages + * + * @category Database + * @package DB + * @author Stig Bakken + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_Error extends PEAR_Error +{ + // {{{ constructor + + /** + * DB_Error constructor + * + * @param mixed $code DB error code, or string with error message + * @param int $mode what "error mode" to operate in + * @param int $level what error level to use for $mode & + * PEAR_ERROR_TRIGGER + * @param mixed $debuginfo additional debug info, such as the last query + * + * @see PEAR_Error + */ + function DB_Error($code = DB_ERROR, $mode = PEAR_ERROR_RETURN, + $level = E_USER_NOTICE, $debuginfo = null) + { + if (is_int($code)) { + $this->PEAR_Error('DB Error: ' . DB::errorMessage($code), $code, + $mode, $level, $debuginfo); + } else { + $this->PEAR_Error("DB Error: $code", DB_ERROR, + $mode, $level, $debuginfo); + } + } + + // }}} +} + +// }}} +// {{{ class DB_result + +/** + * This class implements a wrapper for a DB result set + * + * A new instance of this class will be returned by the DB implementation + * after processing a query that returns data. + * + * @category Database + * @package DB + * @author Stig Bakken + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_result +{ + // {{{ properties + + /** + * Should results be freed automatically when there are no more rows? + * @var boolean + * @see DB_common::$options + */ + var $autofree; + + /** + * A reference to the DB_ object + * @var object + */ + var $dbh; + + /** + * The current default fetch mode + * @var integer + * @see DB_common::$fetchmode + */ + var $fetchmode; + + /** + * The name of the class into which results should be fetched when + * DB_FETCHMODE_OBJECT is in effect + * + * @var string + * @see DB_common::$fetchmode_object_class + */ + var $fetchmode_object_class; + + /** + * The number of rows to fetch from a limit query + * @var integer + */ + var $limit_count = null; + + /** + * The row to start fetching from in limit queries + * @var integer + */ + var $limit_from = null; + + /** + * The execute parameters that created this result + * @var array + * @since Property available since Release 1.7.0 + */ + var $parameters; + + /** + * The query string that created this result + * + * Copied here incase it changes in $dbh, which is referenced + * + * @var string + * @since Property available since Release 1.7.0 + */ + var $query; + + /** + * The query result resource id created by PHP + * @var resource + */ + var $result; + + /** + * The present row being dealt with + * @var integer + */ + var $row_counter = null; + + /** + * The prepared statement resource id created by PHP in $dbh + * + * This resource is only available when the result set was created using + * a driver's native execute() method, not PEAR DB's emulated one. + * + * Copied here incase it changes in $dbh, which is referenced + * + * {@internal Mainly here because the InterBase/Firebird API is only + * able to retrieve data from result sets if the statemnt handle is + * still in scope.}} + * + * @var resource + * @since Property available since Release 1.7.0 + */ + var $statement; + + + // }}} + // {{{ constructor + + /** + * This constructor sets the object's properties + * + * @param object &$dbh the DB object reference + * @param resource $result the result resource id + * @param array $options an associative array with result options + * + * @return void + */ + function DB_result(&$dbh, $result, $options = array()) + { + $this->autofree = $dbh->options['autofree']; + $this->dbh = &$dbh; + $this->fetchmode = $dbh->fetchmode; + $this->fetchmode_object_class = $dbh->fetchmode_object_class; + $this->parameters = $dbh->last_parameters; + $this->query = $dbh->last_query; + $this->result = $result; + $this->statement = empty($dbh->last_stmt) ? null : $dbh->last_stmt; + foreach ($options as $key => $value) { + $this->setOption($key, $value); + } + } + + /** + * Set options for the DB_result object + * + * @param string $key the option to set + * @param mixed $value the value to set the option to + * + * @return void + */ + function setOption($key, $value = null) + { + switch ($key) { + case 'limit_from': + $this->limit_from = $value; + break; + case 'limit_count': + $this->limit_count = $value; + } + } + + // }}} + // {{{ fetchRow() + + /** + * Fetch a row of data and return it by reference into an array + * + * The type of array returned can be controlled either by setting this + * method's $fetchmode parameter or by changing the default + * fetch mode setFetchMode() before calling this method. + * + * There are two options for standardizing the information returned + * from databases, ensuring their values are consistent when changing + * DBMS's. These portability options can be turned on when creating a + * new DB object or by using setOption(). + * + * + DB_PORTABILITY_LOWERCASE + * convert names of fields to lower case + * + * + DB_PORTABILITY_RTRIM + * right trim the data + * + * @param int $fetchmode the constant indicating how to format the data + * @param int $rownum the row number to fetch (index starts at 0) + * + * @return mixed an array or object containing the row's data, + * NULL when the end of the result set is reached + * or a DB_Error object on failure. + * + * @see DB_common::setOption(), DB_common::setFetchMode() + */ + function &fetchRow($fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) + { + if ($fetchmode === DB_FETCHMODE_DEFAULT) { + $fetchmode = $this->fetchmode; + } + if ($fetchmode === DB_FETCHMODE_OBJECT) { + $fetchmode = DB_FETCHMODE_ASSOC; + $object_class = $this->fetchmode_object_class; + } + if (is_null($rownum) && $this->limit_from !== null) { + if ($this->row_counter === null) { + $this->row_counter = $this->limit_from; + // Skip rows + if ($this->dbh->features['limit'] === false) { + $i = 0; + while ($i++ < $this->limit_from) { + $this->dbh->fetchInto($this->result, $arr, $fetchmode); + } + } + } + if ($this->row_counter >= ($this->limit_from + $this->limit_count)) + { + if ($this->autofree) { + $this->free(); + } + $tmp = null; + return $tmp; + } + if ($this->dbh->features['limit'] === 'emulate') { + $rownum = $this->row_counter; + } + $this->row_counter++; + } + $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); + if ($res === DB_OK) { + if (isset($object_class)) { + // The default mode is specified in the + // DB_common::fetchmode_object_class property + if ($object_class == 'stdClass') { + $arr = (object) $arr; + } else { + $arr = new $object_class($arr); + } + } + return $arr; + } + if ($res == null && $this->autofree) { + $this->free(); + } + return $res; + } + + // }}} + // {{{ fetchInto() + + /** + * Fetch a row of data into an array which is passed by reference + * + * The type of array returned can be controlled either by setting this + * method's $fetchmode parameter or by changing the default + * fetch mode setFetchMode() before calling this method. + * + * There are two options for standardizing the information returned + * from databases, ensuring their values are consistent when changing + * DBMS's. These portability options can be turned on when creating a + * new DB object or by using setOption(). + * + * + DB_PORTABILITY_LOWERCASE + * convert names of fields to lower case + * + * + DB_PORTABILITY_RTRIM + * right trim the data + * + * @param array &$arr the variable where the data should be placed + * @param int $fetchmode the constant indicating how to format the data + * @param int $rownum the row number to fetch (index starts at 0) + * + * @return mixed DB_OK if a row is processed, NULL when the end of the + * result set is reached or a DB_Error object on failure + * + * @see DB_common::setOption(), DB_common::setFetchMode() + */ + function fetchInto(&$arr, $fetchmode = DB_FETCHMODE_DEFAULT, $rownum = null) + { + if ($fetchmode === DB_FETCHMODE_DEFAULT) { + $fetchmode = $this->fetchmode; + } + if ($fetchmode === DB_FETCHMODE_OBJECT) { + $fetchmode = DB_FETCHMODE_ASSOC; + $object_class = $this->fetchmode_object_class; + } + if (is_null($rownum) && $this->limit_from !== null) { + if ($this->row_counter === null) { + $this->row_counter = $this->limit_from; + // Skip rows + if ($this->dbh->features['limit'] === false) { + $i = 0; + while ($i++ < $this->limit_from) { + $this->dbh->fetchInto($this->result, $arr, $fetchmode); + } + } + } + if ($this->row_counter >= ( + $this->limit_from + $this->limit_count)) + { + if ($this->autofree) { + $this->free(); + } + return null; + } + if ($this->dbh->features['limit'] === 'emulate') { + $rownum = $this->row_counter; + } + + $this->row_counter++; + } + $res = $this->dbh->fetchInto($this->result, $arr, $fetchmode, $rownum); + if ($res === DB_OK) { + if (isset($object_class)) { + // default mode specified in the + // DB_common::fetchmode_object_class property + if ($object_class == 'stdClass') { + $arr = (object) $arr; + } else { + $arr = new $object_class($arr); + } + } + return DB_OK; + } + if ($res == null && $this->autofree) { + $this->free(); + } + return $res; + } + + // }}} + // {{{ numCols() + + /** + * Get the the number of columns in a result set + * + * @return int the number of columns. A DB_Error object on failure. + */ + function numCols() + { + return $this->dbh->numCols($this->result); + } + + // }}} + // {{{ numRows() + + /** + * Get the number of rows in a result set + * + * @return int the number of rows. A DB_Error object on failure. + */ + function numRows() + { + if ($this->dbh->features['numrows'] === 'emulate' + && $this->dbh->options['portability'] & DB_PORTABILITY_NUMROWS) + { + if ($this->dbh->features['prepare']) { + $res = $this->dbh->query($this->query, $this->parameters); + } else { + $res = $this->dbh->query($this->query); + } + if (DB::isError($res)) { + return $res; + } + $i = 0; + while ($res->fetchInto($tmp, DB_FETCHMODE_ORDERED)) { + $i++; + } + $count = $i; + } else { + $count = $this->dbh->numRows($this->result); + } + + /* fbsql is checked for here because limit queries are implemented + * using a TOP() function, which results in fbsql_num_rows still + * returning the total number of rows that would have been returned, + * rather than the real number. As a result, we'll just do the limit + * calculations for fbsql in the same way as a database with emulated + * limits. Unfortunately, we can't just do this in DB_fbsql::numRows() + * because that only gets the result resource, rather than the full + * DB_Result object. */ + if (($this->dbh->features['limit'] === 'emulate' + && $this->limit_from !== null) + || $this->dbh->phptype == 'fbsql') { + $limit_count = is_null($this->limit_count) ? $count : $this->limit_count; + if ($count < $this->limit_from) { + $count = 0; + } elseif ($count < ($this->limit_from + $limit_count)) { + $count -= $this->limit_from; + } else { + $count = $limit_count; + } + } + + return $count; + } + + // }}} + // {{{ nextResult() + + /** + * Get the next result if a batch of queries was executed + * + * @return bool true if a new result is available or false if not + */ + function nextResult() + { + return $this->dbh->nextResult($this->result); + } + + // }}} + // {{{ free() + + /** + * Frees the resources allocated for this result set + * + * @return bool true on success. A DB_Error object on failure. + */ + function free() + { + $err = $this->dbh->freeResult($this->result); + if (DB::isError($err)) { + return $err; + } + $this->result = false; + $this->statement = false; + return true; + } + + // }}} + // {{{ tableInfo() + + /** + * @see DB_common::tableInfo() + * @deprecated Method deprecated some time before Release 1.2 + */ + function tableInfo($mode = null) + { + if (is_string($mode)) { + return $this->dbh->raiseError(DB_ERROR_NEED_MORE_DATA); + } + return $this->dbh->tableInfo($this, $mode); + } + + // }}} + // {{{ getQuery() + + /** + * Determine the query string that created this result + * + * @return string the query string + * + * @since Method available since Release 1.7.0 + */ + function getQuery() + { + return $this->query; + } + + // }}} + // {{{ getRowCounter() + + /** + * Tells which row number is currently being processed + * + * @return integer the current row being looked at. Starts at 1. + */ + function getRowCounter() + { + return $this->row_counter; + } + + // }}} +} + +// }}} +// {{{ class DB_row + +/** + * PEAR DB Row Object + * + * The object contains a row of data from a result set. Each column's data + * is placed in a property named for the column. + * + * @category Database + * @package DB + * @author Stig Bakken + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + * @see DB_common::setFetchMode() + */ +class DB_row +{ + // {{{ constructor + + /** + * The constructor places a row's data into properties of this object + * + * @param array the array containing the row's data + * + * @return void + */ + function DB_row(&$arr) + { + foreach ($arr as $key => $value) { + $this->$key = &$arr[$key]; + } + } + + // }}} +} + +// }}} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/common.php b/common/PEAR/DB/common.php new file mode 100644 index 0000000..b7bb331 --- /dev/null +++ b/common/PEAR/DB/common.php @@ -0,0 +1,2257 @@ + + * @author Tomas V.V. Cox + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: common.php,v 1.143 2007/09/21 13:40:41 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the PEAR class so it can be extended from + */ +require_once 'PEAR.php'; + +/** + * DB_common is the base class from which each database driver class extends + * + * All common methods are declared here. If a given DBMS driver contains + * a particular method, that method will overload the one here. + * + * @category Database + * @package DB + * @author Stig Bakken + * @author Tomas V.V. Cox + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_common extends PEAR +{ + // {{{ properties + + /** + * The current default fetch mode + * @var integer + */ + var $fetchmode = DB_FETCHMODE_ORDERED; + + /** + * The name of the class into which results should be fetched when + * DB_FETCHMODE_OBJECT is in effect + * + * @var string + */ + var $fetchmode_object_class = 'stdClass'; + + /** + * Was a connection present when the object was serialized()? + * @var bool + * @see DB_common::__sleep(), DB_common::__wake() + */ + var $was_connected = null; + + /** + * The most recently executed query + * @var string + */ + var $last_query = ''; + + /** + * Run-time configuration options + * + * The 'optimize' option has been deprecated. Use the 'portability' + * option instead. + * + * @var array + * @see DB_common::setOption() + */ + var $options = array( + 'result_buffering' => 500, + 'persistent' => false, + 'ssl' => false, + 'debug' => 0, + 'seqname_format' => '%s_seq', + 'autofree' => false, + 'portability' => DB_PORTABILITY_NONE, + 'optimize' => 'performance', // Deprecated. Use 'portability'. + ); + + /** + * The parameters from the most recently executed query + * @var array + * @since Property available since Release 1.7.0 + */ + var $last_parameters = array(); + + /** + * The elements from each prepared statement + * @var array + */ + var $prepare_tokens = array(); + + /** + * The data types of the various elements in each prepared statement + * @var array + */ + var $prepare_types = array(); + + /** + * The prepared queries + * @var array + */ + var $prepared_queries = array(); + + /** + * Flag indicating that the last query was a manipulation query. + * @access protected + * @var boolean + */ + var $_last_query_manip = false; + + /** + * Flag indicating that the next query must be a manipulation + * query. + * @access protected + * @var boolean + */ + var $_next_query_manip = false; + + + // }}} + // {{{ DB_common + + /** + * This constructor calls $this->PEAR('DB_Error') + * + * @return void + */ + function DB_common() + { + $this->PEAR('DB_Error'); + } + + // }}} + // {{{ __sleep() + + /** + * Automatically indicates which properties should be saved + * when PHP's serialize() function is called + * + * @return array the array of properties names that should be saved + */ + function __sleep() + { + if ($this->connection) { + // Don't disconnect(), people use serialize() for many reasons + $this->was_connected = true; + } else { + $this->was_connected = false; + } + if (isset($this->autocommit)) { + return array('autocommit', + 'dbsyntax', + 'dsn', + 'features', + 'fetchmode', + 'fetchmode_object_class', + 'options', + 'was_connected', + ); + } else { + return array('dbsyntax', + 'dsn', + 'features', + 'fetchmode', + 'fetchmode_object_class', + 'options', + 'was_connected', + ); + } + } + + // }}} + // {{{ __wakeup() + + /** + * Automatically reconnects to the database when PHP's unserialize() + * function is called + * + * The reconnection attempt is only performed if the object was connected + * at the time PHP's serialize() function was run. + * + * @return void + */ + function __wakeup() + { + if ($this->was_connected) { + $this->connect($this->dsn, $this->options); + } + } + + // }}} + // {{{ __toString() + + /** + * Automatic string conversion for PHP 5 + * + * @return string a string describing the current PEAR DB object + * + * @since Method available since Release 1.7.0 + */ + function __toString() + { + $info = strtolower(get_class($this)); + $info .= ': (phptype=' . $this->phptype . + ', dbsyntax=' . $this->dbsyntax . + ')'; + if ($this->connection) { + $info .= ' [connected]'; + } + return $info; + } + + // }}} + // {{{ toString() + + /** + * DEPRECATED: String conversion method + * + * @return string a string describing the current PEAR DB object + * + * @deprecated Method deprecated in Release 1.7.0 + */ + function toString() + { + return $this->__toString(); + } + + // }}} + // {{{ quoteString() + + /** + * DEPRECATED: Quotes a string so it can be safely used within string + * delimiters in a query + * + * @param string $string the string to be quoted + * + * @return string the quoted string + * + * @see DB_common::quoteSmart(), DB_common::escapeSimple() + * @deprecated Method deprecated some time before Release 1.2 + */ + function quoteString($string) + { + $string = $this->quote($string); + if ($string{0} == "'") { + return substr($string, 1, -1); + } + return $string; + } + + // }}} + // {{{ quote() + + /** + * DEPRECATED: Quotes a string so it can be safely used in a query + * + * @param string $string the string to quote + * + * @return string the quoted string or the string NULL + * if the value submitted is null. + * + * @see DB_common::quoteSmart(), DB_common::escapeSimple() + * @deprecated Deprecated in release 1.6.0 + */ + function quote($string = null) + { + return ($string === null) ? 'NULL' + : "'" . str_replace("'", "''", $string) . "'"; + } + + // }}} + // {{{ quoteIdentifier() + + /** + * Quotes a string so it can be safely used as a table or column name + * + * Delimiting style depends on which database driver is being used. + * + * NOTE: just because you CAN use delimited identifiers doesn't mean + * you SHOULD use them. In general, they end up causing way more + * problems than they solve. + * + * Portability is broken by using the following characters inside + * delimited identifiers: + * + backtick (`) -- due to MySQL + * + double quote (") -- due to Oracle + * + brackets ([ or ]) -- due to Access + * + * Delimited identifiers are known to generally work correctly under + * the following drivers: + * + mssql + * + mysql + * + mysqli + * + oci8 + * + odbc(access) + * + odbc(db2) + * + pgsql + * + sqlite + * + sybase (must execute set quoted_identifier on sometime + * prior to use) + * + * InterBase doesn't seem to be able to use delimited identifiers + * via PHP 4. They work fine under PHP 5. + * + * @param string $str the identifier name to be quoted + * + * @return string the quoted identifier + * + * @since Method available since Release 1.6.0 + */ + function quoteIdentifier($str) + { + return '"' . str_replace('"', '""', $str) . '"'; + } + + // }}} + // {{{ quoteSmart() + + /** + * Formats input so it can be safely used in a query + * + * The output depends on the PHP data type of input and the database + * type being used. + * + * @param mixed $in the data to be formatted + * + * @return mixed the formatted data. The format depends on the input's + * PHP type: + *
    + *
  • + * input -> returns + *
  • + *
  • + * null -> the string NULL + *
  • + *
  • + * integer or double -> the unquoted number + *
  • + *
  • + * bool -> output depends on the driver in use + * Most drivers return integers: 1 if + * true or 0 if + * false. + * Some return strings: TRUE if + * true or FALSE if + * false. + * Finally one returns strings: T if + * true or F if + * false. Here is a list of each DBMS, + * the values returned and the suggested column type: + *
      + *
    • + * dbase -> T/F + * (Logical) + *
    • + *
    • + * fbase -> TRUE/FALSE + * (BOOLEAN) + *
    • + *
    • + * ibase -> 1/0 + * (SMALLINT) [1] + *
    • + *
    • + * ifx -> 1/0 + * (SMALLINT) [1] + *
    • + *
    • + * msql -> 1/0 + * (INTEGER) + *
    • + *
    • + * mssql -> 1/0 + * (BIT) + *
    • + *
    • + * mysql -> 1/0 + * (TINYINT(1)) + *
    • + *
    • + * mysqli -> 1/0 + * (TINYINT(1)) + *
    • + *
    • + * oci8 -> 1/0 + * (NUMBER(1)) + *
    • + *
    • + * odbc -> 1/0 + * (SMALLINT) [1] + *
    • + *
    • + * pgsql -> TRUE/FALSE + * (BOOLEAN) + *
    • + *
    • + * sqlite -> 1/0 + * (INTEGER) + *
    • + *
    • + * sybase -> 1/0 + * (TINYINT(1)) + *
    • + *
    + * [1] Accommodate the lowest common denominator because not all + * versions of have BOOLEAN. + *
  • + *
  • + * other (including strings and numeric strings) -> + * the data with single quotes escaped by preceeding + * single quotes, backslashes are escaped by preceeding + * backslashes, then the whole string is encapsulated + * between single quotes + *
  • + *
+ * + * @see DB_common::escapeSimple() + * @since Method available since Release 1.6.0 + */ + function quoteSmart($in) + { + if (is_int($in)) { + return $in; + } elseif (is_float($in)) { + return $this->quoteFloat($in); + } elseif (is_bool($in)) { + return $this->quoteBoolean($in); + } elseif (is_null($in)) { + return 'NULL'; + } else { + if ($this->dbsyntax == 'access' + && preg_match('/^#.+#$/', $in)) + { + return $this->escapeSimple($in); + } + return "'" . $this->escapeSimple($in) . "'"; + } + } + + // }}} + // {{{ quoteBoolean() + + /** + * Formats a boolean value for use within a query in a locale-independent + * manner. + * + * @param boolean the boolean value to be quoted. + * @return string the quoted string. + * @see DB_common::quoteSmart() + * @since Method available since release 1.7.8. + */ + function quoteBoolean($boolean) { + return $boolean ? '1' : '0'; + } + + // }}} + // {{{ quoteFloat() + + /** + * Formats a float value for use within a query in a locale-independent + * manner. + * + * @param float the float value to be quoted. + * @return string the quoted string. + * @see DB_common::quoteSmart() + * @since Method available since release 1.7.8. + */ + function quoteFloat($float) { + return "'".$this->escapeSimple(str_replace(',', '.', strval(floatval($float))))."'"; + } + + // }}} + // {{{ escapeSimple() + + /** + * Escapes a string according to the current DBMS's standards + * + * In SQLite, this makes things safe for inserts/updates, but may + * cause problems when performing text comparisons against columns + * containing binary data. See the + * {@link http://php.net/sqlite_escape_string PHP manual} for more info. + * + * @param string $str the string to be escaped + * + * @return string the escaped string + * + * @see DB_common::quoteSmart() + * @since Method available since Release 1.6.0 + */ + function escapeSimple($str) + { + return str_replace("'", "''", $str); + } + + // }}} + // {{{ provides() + + /** + * Tells whether the present driver supports a given feature + * + * @param string $feature the feature you're curious about + * + * @return bool whether this driver supports $feature + */ + function provides($feature) + { + return $this->features[$feature]; + } + + // }}} + // {{{ setFetchMode() + + /** + * Sets the fetch mode that should be used by default for query results + * + * @param integer $fetchmode DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC + * or DB_FETCHMODE_OBJECT + * @param string $object_class the class name of the object to be returned + * by the fetch methods when the + * DB_FETCHMODE_OBJECT mode is selected. + * If no class is specified by default a cast + * to object from the assoc array row will be + * done. There is also the posibility to use + * and extend the 'DB_row' class. + * + * @see DB_FETCHMODE_ORDERED, DB_FETCHMODE_ASSOC, DB_FETCHMODE_OBJECT + */ + function setFetchMode($fetchmode, $object_class = 'stdClass') + { + switch ($fetchmode) { + case DB_FETCHMODE_OBJECT: + $this->fetchmode_object_class = $object_class; + case DB_FETCHMODE_ORDERED: + case DB_FETCHMODE_ASSOC: + $this->fetchmode = $fetchmode; + break; + default: + return $this->raiseError('invalid fetchmode mode'); + } + } + + // }}} + // {{{ setOption() + + /** + * Sets run-time configuration options for PEAR DB + * + * Options, their data types, default values and description: + *
    + *
  • + * autofree boolean = false + *
    should results be freed automatically when there are no + * more rows? + *
  • + * result_buffering integer = 500 + *
    how many rows of the result set should be buffered? + *
    In mysql: mysql_unbuffered_query() is used instead of + * mysql_query() if this value is 0. (Release 1.7.0) + *
    In oci8: this value is passed to ocisetprefetch(). + * (Release 1.7.0) + *
  • + * debug integer = 0 + *
    debug level + *
  • + * persistent boolean = false + *
    should the connection be persistent? + *
  • + * portability integer = DB_PORTABILITY_NONE + *
    portability mode constant (see below) + *
  • + * seqname_format string = %s_seq + *
    the sprintf() format string used on sequence names. This + * format is applied to sequence names passed to + * createSequence(), nextID() and dropSequence(). + *
  • + * ssl boolean = false + *
    use ssl to connect? + *
  • + *
+ * + * ----------------------------------------- + * + * PORTABILITY MODES + * + * These modes are bitwised, so they can be combined using | + * and removed using ^. See the examples section below on how + * to do this. + * + * DB_PORTABILITY_NONE + * turn off all portability features + * + * This mode gets automatically turned on if the deprecated + * optimize option gets set to performance. + * + * + * DB_PORTABILITY_LOWERCASE + * convert names of tables and fields to lower case when using + * get*(), fetch*() and tableInfo() + * + * This mode gets automatically turned on in the following databases + * if the deprecated option optimize gets set to + * portability: + * + oci8 + * + * + * DB_PORTABILITY_RTRIM + * right trim the data output by get*() fetch*() + * + * + * DB_PORTABILITY_DELETE_COUNT + * force reporting the number of rows deleted + * + * Some DBMS's don't count the number of rows deleted when performing + * simple DELETE FROM tablename queries. This portability + * mode tricks such DBMS's into telling the count by adding + * WHERE 1=1 to the end of DELETE queries. + * + * This mode gets automatically turned on in the following databases + * if the deprecated option optimize gets set to + * portability: + * + fbsql + * + mysql + * + mysqli + * + sqlite + * + * + * DB_PORTABILITY_NUMROWS + * enable hack that makes numRows() work in Oracle + * + * This mode gets automatically turned on in the following databases + * if the deprecated option optimize gets set to + * portability: + * + oci8 + * + * + * DB_PORTABILITY_ERRORS + * makes certain error messages in certain drivers compatible + * with those from other DBMS's + * + * + mysql, mysqli: change unique/primary key constraints + * DB_ERROR_ALREADY_EXISTS -> DB_ERROR_CONSTRAINT + * + * + odbc(access): MS's ODBC driver reports 'no such field' as code + * 07001, which means 'too few parameters.' When this option is on + * that code gets mapped to DB_ERROR_NOSUCHFIELD. + * DB_ERROR_MISMATCH -> DB_ERROR_NOSUCHFIELD + * + * DB_PORTABILITY_NULL_TO_EMPTY + * convert null values to empty strings in data output by get*() and + * fetch*(). Needed because Oracle considers empty strings to be null, + * while most other DBMS's know the difference between empty and null. + * + * + * DB_PORTABILITY_ALL + * turn on all portability features + * + * ----------------------------------------- + * + * Example 1. Simple setOption() example + * + * $db->setOption('autofree', true); + * + * + * Example 2. Portability for lowercasing and trimming + * + * $db->setOption('portability', + * DB_PORTABILITY_LOWERCASE | DB_PORTABILITY_RTRIM); + * + * + * Example 3. All portability options except trimming + * + * $db->setOption('portability', + * DB_PORTABILITY_ALL ^ DB_PORTABILITY_RTRIM); + * + * + * @param string $option option name + * @param mixed $value value for the option + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::$options + */ + function setOption($option, $value) + { + if (isset($this->options[$option])) { + $this->options[$option] = $value; + + /* + * Backwards compatibility check for the deprecated 'optimize' + * option. Done here in case settings change after connecting. + */ + if ($option == 'optimize') { + if ($value == 'portability') { + switch ($this->phptype) { + case 'oci8': + $this->options['portability'] = + DB_PORTABILITY_LOWERCASE | + DB_PORTABILITY_NUMROWS; + break; + case 'fbsql': + case 'mysql': + case 'mysqli': + case 'sqlite': + $this->options['portability'] = + DB_PORTABILITY_DELETE_COUNT; + break; + } + } else { + $this->options['portability'] = DB_PORTABILITY_NONE; + } + } + + return DB_OK; + } + return $this->raiseError("unknown option $option"); + } + + // }}} + // {{{ getOption() + + /** + * Returns the value of an option + * + * @param string $option the option name you're curious about + * + * @return mixed the option's value + */ + function getOption($option) + { + if (isset($this->options[$option])) { + return $this->options[$option]; + } + return $this->raiseError("unknown option $option"); + } + + // }}} + // {{{ prepare() + + /** + * Prepares a query for multiple execution with execute() + * + * Creates a query that can be run multiple times. Each time it is run, + * the placeholders, if any, will be replaced by the contents of + * execute()'s $data argument. + * + * Three types of placeholders can be used: + * + ? scalar value (i.e. strings, integers). The system + * will automatically quote and escape the data. + * + ! value is inserted 'as is' + * + & requires a file name. The file's contents get + * inserted into the query (i.e. saving binary + * data in a db) + * + * Example 1. + * + * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); + * $data = array( + * "John's text", + * "'it''s good'", + * 'filename.txt' + * ); + * $res = $db->execute($sth, $data); + * + * + * Use backslashes to escape placeholder characters if you don't want + * them to be interpreted as placeholders: + *
+     *    "UPDATE foo SET col=? WHERE col='over \& under'"
+     * 
+ * + * With some database backends, this is emulated. + * + * {@internal ibase and oci8 have their own prepare() methods.}} + * + * @param string $query the query to be prepared + * + * @return mixed DB statement resource on success. A DB_Error object + * on failure. + * + * @see DB_common::execute() + */ + function prepare($query) + { + $tokens = preg_split('/((?prepare_tokens[] = &$newtokens; + end($this->prepare_tokens); + + $k = key($this->prepare_tokens); + $this->prepare_types[$k] = $types; + $this->prepared_queries[$k] = implode(' ', $newtokens); + + return $k; + } + + // }}} + // {{{ autoPrepare() + + /** + * Automaticaly generates an insert or update query and pass it to prepare() + * + * @param string $table the table name + * @param array $table_fields the array of field names + * @param int $mode a type of query to make: + * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE + * @param string $where for update queries: the WHERE clause to + * append to the SQL statement. Don't + * include the "WHERE" keyword. + * + * @return resource the query handle + * + * @uses DB_common::prepare(), DB_common::buildManipSQL() + */ + function autoPrepare($table, $table_fields, $mode = DB_AUTOQUERY_INSERT, + $where = false) + { + $query = $this->buildManipSQL($table, $table_fields, $mode, $where); + if (DB::isError($query)) { + return $query; + } + return $this->prepare($query); + } + + // }}} + // {{{ autoExecute() + + /** + * Automaticaly generates an insert or update query and call prepare() + * and execute() with it + * + * @param string $table the table name + * @param array $fields_values the associative array where $key is a + * field name and $value its value + * @param int $mode a type of query to make: + * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE + * @param string $where for update queries: the WHERE clause to + * append to the SQL statement. Don't + * include the "WHERE" keyword. + * + * @return mixed a new DB_result object for successful SELECT queries + * or DB_OK for successul data manipulation queries. + * A DB_Error object on failure. + * + * @uses DB_common::autoPrepare(), DB_common::execute() + */ + function autoExecute($table, $fields_values, $mode = DB_AUTOQUERY_INSERT, + $where = false) + { + $sth = $this->autoPrepare($table, array_keys($fields_values), $mode, + $where); + if (DB::isError($sth)) { + return $sth; + } + $ret = $this->execute($sth, array_values($fields_values)); + $this->freePrepared($sth); + return $ret; + + } + + // }}} + // {{{ buildManipSQL() + + /** + * Produces an SQL query string for autoPrepare() + * + * Example: + *
+     * buildManipSQL('table_sql', array('field1', 'field2', 'field3'),
+     *               DB_AUTOQUERY_INSERT);
+     * 
+ * + * That returns + * + * INSERT INTO table_sql (field1,field2,field3) VALUES (?,?,?) + * + * + * NOTES: + * - This belongs more to a SQL Builder class, but this is a simple + * facility. + * - Be carefull! If you don't give a $where param with an UPDATE + * query, all the records of the table will be updated! + * + * @param string $table the table name + * @param array $table_fields the array of field names + * @param int $mode a type of query to make: + * DB_AUTOQUERY_INSERT or DB_AUTOQUERY_UPDATE + * @param string $where for update queries: the WHERE clause to + * append to the SQL statement. Don't + * include the "WHERE" keyword. + * + * @return string the sql query for autoPrepare() + */ + function buildManipSQL($table, $table_fields, $mode, $where = false) + { + if (count($table_fields) == 0) { + return $this->raiseError(DB_ERROR_NEED_MORE_DATA); + } + $first = true; + switch ($mode) { + case DB_AUTOQUERY_INSERT: + $values = ''; + $names = ''; + foreach ($table_fields as $value) { + if ($first) { + $first = false; + } else { + $names .= ','; + $values .= ','; + } + $names .= $value; + $values .= '?'; + } + return "INSERT INTO $table ($names) VALUES ($values)"; + case DB_AUTOQUERY_UPDATE: + $set = ''; + foreach ($table_fields as $value) { + if ($first) { + $first = false; + } else { + $set .= ','; + } + $set .= "$value = ?"; + } + $sql = "UPDATE $table SET $set"; + if ($where) { + $sql .= " WHERE $where"; + } + return $sql; + default: + return $this->raiseError(DB_ERROR_SYNTAX); + } + } + + // }}} + // {{{ execute() + + /** + * Executes a DB statement prepared with prepare() + * + * Example 1. + * + * $sth = $db->prepare('INSERT INTO tbl (a, b, c) VALUES (?, !, &)'); + * $data = array( + * "John's text", + * "'it''s good'", + * 'filename.txt' + * ); + * $res = $db->execute($sth, $data); + * + * + * @param resource $stmt a DB statement resource returned from prepare() + * @param mixed $data array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed a new DB_result object for successful SELECT queries + * or DB_OK for successul data manipulation queries. + * A DB_Error object on failure. + * + * {@internal ibase and oci8 have their own execute() methods.}} + * + * @see DB_common::prepare() + */ + function &execute($stmt, $data = array()) + { + $realquery = $this->executeEmulateQuery($stmt, $data); + if (DB::isError($realquery)) { + return $realquery; + } + $result = $this->simpleQuery($realquery); + + if ($result === DB_OK || DB::isError($result)) { + return $result; + } else { + $tmp = new DB_result($this, $result); + return $tmp; + } + } + + // }}} + // {{{ executeEmulateQuery() + + /** + * Emulates executing prepared statements if the DBMS not support them + * + * @param resource $stmt a DB statement resource returned from execute() + * @param mixed $data array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed a string containing the real query run when emulating + * prepare/execute. A DB_Error object on failure. + * + * @access protected + * @see DB_common::execute() + */ + function executeEmulateQuery($stmt, $data = array()) + { + $stmt = (int)$stmt; + $data = (array)$data; + $this->last_parameters = $data; + + if (count($this->prepare_types[$stmt]) != count($data)) { + $this->last_query = $this->prepared_queries[$stmt]; + return $this->raiseError(DB_ERROR_MISMATCH); + } + + $realquery = $this->prepare_tokens[$stmt][0]; + + $i = 0; + foreach ($data as $value) { + if ($this->prepare_types[$stmt][$i] == DB_PARAM_SCALAR) { + $realquery .= $this->quoteSmart($value); + } elseif ($this->prepare_types[$stmt][$i] == DB_PARAM_OPAQUE) { + $fp = @fopen($value, 'rb'); + if (!$fp) { + return $this->raiseError(DB_ERROR_ACCESS_VIOLATION); + } + $realquery .= $this->quoteSmart(fread($fp, filesize($value))); + fclose($fp); + } else { + $realquery .= $value; + } + + $realquery .= $this->prepare_tokens[$stmt][++$i]; + } + + return $realquery; + } + + // }}} + // {{{ executeMultiple() + + /** + * Performs several execute() calls on the same statement handle + * + * $data must be an array indexed numerically + * from 0, one execute call is done for every "row" in the array. + * + * If an error occurs during execute(), executeMultiple() does not + * execute the unfinished rows, but rather returns that error. + * + * @param resource $stmt query handle from prepare() + * @param array $data numeric array containing the + * data to insert into the query + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::prepare(), DB_common::execute() + */ + function executeMultiple($stmt, $data) + { + foreach ($data as $value) { + $res = $this->execute($stmt, $value); + if (DB::isError($res)) { + return $res; + } + } + return DB_OK; + } + + // }}} + // {{{ freePrepared() + + /** + * Frees the internal resources associated with a prepared query + * + * @param resource $stmt the prepared statement's PHP resource + * @param bool $free_resource should the PHP resource be freed too? + * Use false if you need to get data + * from the result set later. + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_common::prepare() + */ + function freePrepared($stmt, $free_resource = true) + { + $stmt = (int)$stmt; + if (isset($this->prepare_tokens[$stmt])) { + unset($this->prepare_tokens[$stmt]); + unset($this->prepare_types[$stmt]); + unset($this->prepared_queries[$stmt]); + return true; + } + return false; + } + + // }}} + // {{{ modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * It is defined here to ensure all drivers have this method available. + * + * @param string $query the query string to modify + * + * @return string the modified query string + * + * @access protected + * @see DB_mysql::modifyQuery(), DB_oci8::modifyQuery(), + * DB_sqlite::modifyQuery() + */ + function modifyQuery($query) + { + return $query; + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * It is defined here to assure that all implementations + * have this method defined. + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + return $query; + } + + // }}} + // {{{ query() + + /** + * Sends a query to the database server + * + * The query string can be either a normal statement to be sent directly + * to the server OR if $params are passed the query can have + * placeholders and it will be passed through prepare() and execute(). + * + * @param string $query the SQL query or the statement to prepare + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed a new DB_result object for successful SELECT queries + * or DB_OK for successul data manipulation queries. + * A DB_Error object on failure. + * + * @see DB_result, DB_common::prepare(), DB_common::execute() + */ + function &query($query, $params = array()) + { + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + if (DB::isError($sth)) { + return $sth; + } + $ret = $this->execute($sth, $params); + $this->freePrepared($sth, false); + return $ret; + } else { + $this->last_parameters = array(); + $result = $this->simpleQuery($query); + if ($result === DB_OK || DB::isError($result)) { + return $result; + } else { + $tmp = new DB_result($this, $result); + return $tmp; + } + } + } + + // }}} + // {{{ limitQuery() + + /** + * Generates and executes a LIMIT query + * + * @param string $query the query + * @param intr $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed a new DB_result object for successful SELECT queries + * or DB_OK for successul data manipulation queries. + * A DB_Error object on failure. + */ + function &limitQuery($query, $from, $count, $params = array()) + { + $query = $this->modifyLimitQuery($query, $from, $count, $params); + if (DB::isError($query)){ + return $query; + } + $result = $this->query($query, $params); + if (is_a($result, 'DB_result')) { + $result->setOption('limit_from', $from); + $result->setOption('limit_count', $count); + } + return $result; + } + + // }}} + // {{{ getOne() + + /** + * Fetches the first column of the first row from a query result + * + * Takes care of doing the query and freeing the results when finished. + * + * @param string $query the SQL query + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return mixed the returned value of the query. + * A DB_Error object on failure. + */ + function &getOne($query, $params = array()) + { + $params = (array)$params; + // modifyLimitQuery() would be nice here, but it causes BC issues + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + if (DB::isError($sth)) { + return $sth; + } + $res = $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res = $this->query($query); + } + + if (DB::isError($res)) { + return $res; + } + + $err = $res->fetchInto($row, DB_FETCHMODE_ORDERED); + $res->free(); + + if ($err !== DB_OK) { + return $err; + } + + return $row[0]; + } + + // }}} + // {{{ getRow() + + /** + * Fetches the first row of data returned from a query result + * + * Takes care of doing the query and freeing the results when finished. + * + * @param string $query the SQL query + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * @param int $fetchmode the fetch mode to use + * + * @return array the first row of results as an array. + * A DB_Error object on failure. + */ + function &getRow($query, $params = array(), + $fetchmode = DB_FETCHMODE_DEFAULT) + { + // compat check, the params and fetchmode parameters used to + // have the opposite order + if (!is_array($params)) { + if (is_array($fetchmode)) { + if ($params === null) { + $tmp = DB_FETCHMODE_DEFAULT; + } else { + $tmp = $params; + } + $params = $fetchmode; + $fetchmode = $tmp; + } elseif ($params !== null) { + $fetchmode = $params; + $params = array(); + } + } + // modifyLimitQuery() would be nice here, but it causes BC issues + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + if (DB::isError($sth)) { + return $sth; + } + $res = $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res = $this->query($query); + } + + if (DB::isError($res)) { + return $res; + } + + $err = $res->fetchInto($row, $fetchmode); + + $res->free(); + + if ($err !== DB_OK) { + return $err; + } + + return $row; + } + + // }}} + // {{{ getCol() + + /** + * Fetches a single column from a query result and returns it as an + * indexed array + * + * @param string $query the SQL query + * @param mixed $col which column to return (integer [column number, + * starting at 0] or string [column name]) + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return array the results as an array. A DB_Error object on failure. + * + * @see DB_common::query() + */ + function &getCol($query, $col = 0, $params = array()) + { + $params = (array)$params; + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + + if (DB::isError($sth)) { + return $sth; + } + + $res = $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res = $this->query($query); + } + + if (DB::isError($res)) { + return $res; + } + + $fetchmode = is_int($col) ? DB_FETCHMODE_ORDERED : DB_FETCHMODE_ASSOC; + + if (!is_array($row = $res->fetchRow($fetchmode))) { + $ret = array(); + } else { + if (!array_key_exists($col, $row)) { + $ret = $this->raiseError(DB_ERROR_NOSUCHFIELD); + } else { + $ret = array($row[$col]); + while (is_array($row = $res->fetchRow($fetchmode))) { + $ret[] = $row[$col]; + } + } + } + + $res->free(); + + if (DB::isError($row)) { + $ret = $row; + } + + return $ret; + } + + // }}} + // {{{ getAssoc() + + /** + * Fetches an entire query result and returns it as an + * associative array using the first column as the key + * + * If the result set contains more than two columns, the value + * will be an array of the values from column 2-n. If the result + * set contains only two columns, the returned value will be a + * scalar with the value of the second column (unless forced to an + * array with the $force_array parameter). A DB error code is + * returned on errors. If the result set contains fewer than two + * columns, a DB_ERROR_TRUNCATED error is returned. + * + * For example, if the table "mytable" contains: + * + *
+     *  ID      TEXT       DATE
+     * --------------------------------
+     *  1       'one'      944679408
+     *  2       'two'      944679408
+     *  3       'three'    944679408
+     * 
+ * + * Then the call getAssoc('SELECT id,text FROM mytable') returns: + *
+     *   array(
+     *     '1' => 'one',
+     *     '2' => 'two',
+     *     '3' => 'three',
+     *   )
+     * 
+ * + * ...while the call getAssoc('SELECT id,text,date FROM mytable') returns: + *
+     *   array(
+     *     '1' => array('one', '944679408'),
+     *     '2' => array('two', '944679408'),
+     *     '3' => array('three', '944679408')
+     *   )
+     * 
+ * + * If the more than one row occurs with the same value in the + * first column, the last row overwrites all previous ones by + * default. Use the $group parameter if you don't want to + * overwrite like this. Example: + * + *
+     * getAssoc('SELECT category,id,name FROM mytable', false, null,
+     *          DB_FETCHMODE_ASSOC, true) returns:
+     *
+     *   array(
+     *     '1' => array(array('id' => '4', 'name' => 'number four'),
+     *                  array('id' => '6', 'name' => 'number six')
+     *            ),
+     *     '9' => array(array('id' => '4', 'name' => 'number four'),
+     *                  array('id' => '6', 'name' => 'number six')
+     *            )
+     *   )
+     * 
+ * + * Keep in mind that database functions in PHP usually return string + * values for results regardless of the database's internal type. + * + * @param string $query the SQL query + * @param bool $force_array used only when the query returns + * exactly two columns. If true, the values + * of the returned array will be one-element + * arrays instead of scalars. + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of + * items passed must match quantity of + * placeholders in query: meaning 1 + * placeholder for non-array parameters or + * 1 placeholder per array element. + * @param int $fetchmode the fetch mode to use + * @param bool $group if true, the values of the returned array + * is wrapped in another array. If the same + * key value (in the first column) repeats + * itself, the values will be appended to + * this array instead of overwriting the + * existing values. + * + * @return array the associative array containing the query results. + * A DB_Error object on failure. + */ + function &getAssoc($query, $force_array = false, $params = array(), + $fetchmode = DB_FETCHMODE_DEFAULT, $group = false) + { + $params = (array)$params; + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + + if (DB::isError($sth)) { + return $sth; + } + + $res = $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res = $this->query($query); + } + + if (DB::isError($res)) { + return $res; + } + if ($fetchmode == DB_FETCHMODE_DEFAULT) { + $fetchmode = $this->fetchmode; + } + $cols = $res->numCols(); + + if ($cols < 2) { + $tmp = $this->raiseError(DB_ERROR_TRUNCATED); + return $tmp; + } + + $results = array(); + + if ($cols > 2 || $force_array) { + // return array values + // XXX this part can be optimized + if ($fetchmode == DB_FETCHMODE_ASSOC) { + while (is_array($row = $res->fetchRow(DB_FETCHMODE_ASSOC))) { + reset($row); + $key = current($row); + unset($row[key($row)]); + if ($group) { + $results[$key][] = $row; + } else { + $results[$key] = $row; + } + } + } elseif ($fetchmode == DB_FETCHMODE_OBJECT) { + while ($row = $res->fetchRow(DB_FETCHMODE_OBJECT)) { + $arr = get_object_vars($row); + $key = current($arr); + if ($group) { + $results[$key][] = $row; + } else { + $results[$key] = $row; + } + } + } else { + while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { + // we shift away the first element to get + // indices running from 0 again + $key = array_shift($row); + if ($group) { + $results[$key][] = $row; + } else { + $results[$key] = $row; + } + } + } + if (DB::isError($row)) { + $results = $row; + } + } else { + // return scalar values + while (is_array($row = $res->fetchRow(DB_FETCHMODE_ORDERED))) { + if ($group) { + $results[$row[0]][] = $row[1]; + } else { + $results[$row[0]] = $row[1]; + } + } + if (DB::isError($row)) { + $results = $row; + } + } + + $res->free(); + + return $results; + } + + // }}} + // {{{ getAll() + + /** + * Fetches all of the rows from a query result + * + * @param string $query the SQL query + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of + * items passed must match quantity of + * placeholders in query: meaning 1 + * placeholder for non-array parameters or + * 1 placeholder per array element. + * @param int $fetchmode the fetch mode to use: + * + DB_FETCHMODE_ORDERED + * + DB_FETCHMODE_ASSOC + * + DB_FETCHMODE_ORDERED | DB_FETCHMODE_FLIPPED + * + DB_FETCHMODE_ASSOC | DB_FETCHMODE_FLIPPED + * + * @return array the nested array. A DB_Error object on failure. + */ + function &getAll($query, $params = array(), + $fetchmode = DB_FETCHMODE_DEFAULT) + { + // compat check, the params and fetchmode parameters used to + // have the opposite order + if (!is_array($params)) { + if (is_array($fetchmode)) { + if ($params === null) { + $tmp = DB_FETCHMODE_DEFAULT; + } else { + $tmp = $params; + } + $params = $fetchmode; + $fetchmode = $tmp; + } elseif ($params !== null) { + $fetchmode = $params; + $params = array(); + } + } + + if (sizeof($params) > 0) { + $sth = $this->prepare($query); + + if (DB::isError($sth)) { + return $sth; + } + + $res = $this->execute($sth, $params); + $this->freePrepared($sth); + } else { + $res = $this->query($query); + } + + if ($res === DB_OK || DB::isError($res)) { + return $res; + } + + $results = array(); + while (DB_OK === $res->fetchInto($row, $fetchmode)) { + if ($fetchmode & DB_FETCHMODE_FLIPPED) { + foreach ($row as $key => $val) { + $results[$key][] = $val; + } + } else { + $results[] = $row; + } + } + + $res->free(); + + if (DB::isError($row)) { + $tmp = $this->raiseError($row); + return $tmp; + } + return $results; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ numRows() + + /** + * Determines the number of rows in a query result + * + * @param resource $result the query result idenifier produced by PHP + * + * @return int the number of rows. A DB_Error object on failure. + */ + function numRows($result) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ getSequenceName() + + /** + * Generates the name used inside the database for a sequence + * + * The createSequence() docblock contains notes about storing sequence + * names. + * + * @param string $sqn the sequence's public name + * + * @return string the sequence's name in the backend + * + * @access protected + * @see DB_common::createSequence(), DB_common::dropSequence(), + * DB_common::nextID(), DB_common::setOption() + */ + function getSequenceName($sqn) + { + return sprintf($this->getOption('seqname_format'), + preg_replace('/[^a-z0-9_.]/i', '_', $sqn)); + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::dropSequence(), + * DB_common::getSequenceName() + */ + function nextId($seq_name, $ondemand = true) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ createSequence() + + /** + * Creates a new sequence + * + * The name of a given sequence is determined by passing the string + * provided in the $seq_name argument through PHP's sprintf() + * function using the value from the seqname_format option as + * the sprintf()'s format argument. + * + * seqname_format is set via setOption(). + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_common::nextID() + */ + function createSequence($seq_name) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_common::nextID() + */ + function dropSequence($seq_name) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ raiseError() + + /** + * Communicates an error and invoke error callbacks, etc + * + * Basically a wrapper for PEAR::raiseError without the message string. + * + * @param mixed integer error code, or a PEAR error object (all + * other parameters are ignored if this parameter is + * an object + * @param int error mode, see PEAR_Error docs + * @param mixed if error mode is PEAR_ERROR_TRIGGER, this is the + * error level (E_USER_NOTICE etc). If error mode is + * PEAR_ERROR_CALLBACK, this is the callback function, + * either as a function name, or as an array of an + * object and method name. For other error modes this + * parameter is ignored. + * @param string extra debug information. Defaults to the last + * query and native error code. + * @param mixed native error code, integer or string depending the + * backend + * + * @return object the PEAR_Error object + * + * @see PEAR_Error + */ + function &raiseError($code = DB_ERROR, $mode = null, $options = null, + $userinfo = null, $nativecode = null) + { + // The error is yet a DB error object + if (is_object($code)) { + // because we the static PEAR::raiseError, our global + // handler should be used if it is set + if ($mode === null && !empty($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + } + $tmp = PEAR::raiseError($code, null, $mode, $options, + null, null, true); + return $tmp; + } + + if ($userinfo === null) { + $userinfo = $this->last_query; + } + + if ($nativecode) { + $userinfo .= ' [nativecode=' . trim($nativecode) . ']'; + } else { + $userinfo .= ' [DB Error: ' . DB::errorMessage($code) . ']'; + } + + $tmp = PEAR::raiseError(null, $code, $mode, $options, $userinfo, + 'DB_Error', true); + return $tmp; + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code produced by the last query + * + * @return mixed the DBMS' error code. A DB_Error object on failure. + */ + function errorNative() + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ errorCode() + + /** + * Maps native error codes to DB's portable ones + * + * Uses the $errorcode_map property defined in each driver. + * + * @param string|int $nativecode the error code returned by the DBMS + * + * @return int the portable DB error code. Return DB_ERROR if the + * current driver doesn't have a mapping for the + * $nativecode submitted. + */ + function errorCode($nativecode) + { + if (isset($this->errorcode_map[$nativecode])) { + return $this->errorcode_map[$nativecode]; + } + // Fall back to DB_ERROR if there was no mapping. + return DB_ERROR; + } + + // }}} + // {{{ errorMessage() + + /** + * Maps a DB error code to a textual message + * + * @param integer $dbcode the DB error code + * + * @return string the error message corresponding to the error code + * submitted. FALSE if the error code is unknown. + * + * @see DB::errorMessage() + */ + function errorMessage($dbcode) + { + return DB::errorMessage($this->errorcode_map[$dbcode]); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * The format of the resulting array depends on which $mode + * you select. The sample output below is based on this query: + *
+     *    SELECT tblFoo.fldID, tblFoo.fldPhone, tblBar.fldId
+     *    FROM tblFoo
+     *    JOIN tblBar ON tblFoo.fldId = tblBar.fldId
+     * 
+ * + *
    + *
  • + * + * null (default) + *
    +     *   [0] => Array (
    +     *       [table] => tblFoo
    +     *       [name] => fldId
    +     *       [type] => int
    +     *       [len] => 11
    +     *       [flags] => primary_key not_null
    +     *   )
    +     *   [1] => Array (
    +     *       [table] => tblFoo
    +     *       [name] => fldPhone
    +     *       [type] => string
    +     *       [len] => 20
    +     *       [flags] =>
    +     *   )
    +     *   [2] => Array (
    +     *       [table] => tblBar
    +     *       [name] => fldId
    +     *       [type] => int
    +     *       [len] => 11
    +     *       [flags] => primary_key not_null
    +     *   )
    +     *   
    + * + *
  • + * + * DB_TABLEINFO_ORDER + * + *

    In addition to the information found in the default output, + * a notation of the number of columns is provided by the + * num_fields element while the order + * element provides an array with the column names as the keys and + * their location index number (corresponding to the keys in the + * the default output) as the values.

    + * + *

    If a result set has identical field names, the last one is + * used.

    + * + *
    +     *   [num_fields] => 3
    +     *   [order] => Array (
    +     *       [fldId] => 2
    +     *       [fldTrans] => 1
    +     *   )
    +     *   
    + * + *
  • + * + * DB_TABLEINFO_ORDERTABLE + * + *

    Similar to DB_TABLEINFO_ORDER but adds more + * dimensions to the array in which the table names are keys and + * the field names are sub-keys. This is helpful for queries that + * join tables which have identical field names.

    + * + *
    +     *   [num_fields] => 3
    +     *   [ordertable] => Array (
    +     *       [tblFoo] => Array (
    +     *           [fldId] => 0
    +     *           [fldPhone] => 1
    +     *       )
    +     *       [tblBar] => Array (
    +     *           [fldId] => 2
    +     *       )
    +     *   )
    +     *   
    + * + *
  • + *
+ * + * The flags element contains a space separated list + * of extra information about the field. This data is inconsistent + * between DBMS's due to the way each DBMS works. + * + primary_key + * + unique_key + * + multiple_key + * + not_null + * + * Most DBMS's only provide the table and flags + * elements if $result is a table name. The following DBMS's + * provide full information from queries: + * + fbsql + * + mysql + * + * If the 'portability' option has DB_PORTABILITY_LOWERCASE + * turned on, the names of tables and fields will be lowercased. + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode either unused or one of the tableInfo modes: + * DB_TABLEINFO_ORDERTABLE, + * DB_TABLEINFO_ORDER or + * DB_TABLEINFO_FULL (which does both). + * These are bitwise, so the first two can be + * combined using |. + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::setOption() + */ + function tableInfo($result, $mode = null) + { + /* + * If the DB_ class has a tableInfo() method, that one + * overrides this one. But, if the driver doesn't have one, + * this method runs and tells users about that fact. + */ + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ getTables() + + /** + * Lists the tables in the current database + * + * @return array the list of tables. A DB_Error object on failure. + * + * @deprecated Method deprecated some time before Release 1.2 + */ + function getTables() + { + return $this->getListOf('tables'); + } + + // }}} + // {{{ getListOf() + + /** + * Lists internal database information + * + * @param string $type type of information being sought. + * Common items being sought are: + * tables, databases, users, views, functions + * Each DBMS's has its own capabilities. + * + * @return array an array listing the items sought. + * A DB DB_Error object on failure. + */ + function getListOf($type) + { + $sql = $this->getSpecialQuery($type); + if ($sql === null) { + $this->last_query = ''; + return $this->raiseError(DB_ERROR_UNSUPPORTED); + } elseif (is_int($sql) || DB::isError($sql)) { + // Previous error + return $this->raiseError($sql); + } elseif (is_array($sql)) { + // Already the result + return $sql; + } + // Launch this query + return $this->getCol($sql); + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + return $this->raiseError(DB_ERROR_UNSUPPORTED); + } + + // }}} + // {{{ nextQueryIsManip() + + /** + * Sets (or unsets) a flag indicating that the next query will be a + * manipulation query, regardless of the usual DB::isManip() heuristics. + * + * @param boolean true to set the flag overriding the isManip() behaviour, + * false to clear it and fall back onto isManip() + * + * @return void + * + * @access public + */ + function nextQueryIsManip($manip) + { + $this->_next_query_manip = $manip; + } + + // }}} + // {{{ _checkManip() + + /** + * Checks if the given query is a manipulation query. This also takes into + * account the _next_query_manip flag and sets the _last_query_manip flag + * (and resets _next_query_manip) according to the result. + * + * @param string The query to check. + * + * @return boolean true if the query is a manipulation query, false + * otherwise + * + * @access protected + */ + function _checkManip($query) + { + if ($this->_next_query_manip || DB::isManip($query)) { + $this->_last_query_manip = true; + } else { + $this->_last_query_manip = false; + } + $this->_next_query_manip = false; + return $this->_last_query_manip; + $manip = $this->_next_query_manip; + } + + // }}} + // {{{ _rtrimArrayValues() + + /** + * Right-trims all strings in an array + * + * @param array $array the array to be trimmed (passed by reference) + * + * @return void + * + * @access protected + */ + function _rtrimArrayValues(&$array) + { + foreach ($array as $key => $value) { + if (is_string($value)) { + $array[$key] = rtrim($value); + } + } + } + + // }}} + // {{{ _convertNullArrayValuesToEmpty() + + /** + * Converts all null values in an array to empty strings + * + * @param array $array the array to be de-nullified (passed by reference) + * + * @return void + * + * @access protected + */ + function _convertNullArrayValuesToEmpty(&$array) + { + foreach ($array as $key => $value) { + if (is_null($value)) { + $array[$key] = ''; + } + } + } + + // }}} +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/dbase.php b/common/PEAR/DB/dbase.php new file mode 100644 index 0000000..90aa2c0 --- /dev/null +++ b/common/PEAR/DB/dbase.php @@ -0,0 +1,510 @@ + + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: dbase.php,v 1.45 2007/09/21 13:40:41 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's dbase extension + * for interacting with dBase databases + * + * These methods overload the ones declared in DB_common. + * + * @category Database + * @package DB + * @author Tomas V.V. Cox + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_dbase extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'dbase'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'dbase'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => false, + 'new_link' => false, + 'numrows' => true, + 'pconnect' => false, + 'prepare' => false, + 'ssl' => false, + 'transactions' => false, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * A means of emulating result resources + * @var array + */ + var $res_row = array(); + + /** + * The quantity of results so far + * + * For emulating result resources. + * + * @var integer + */ + var $result = 0; + + /** + * Maps dbase data type id's to human readable strings + * + * The human readable values are based on the output of PHP's + * dbase_get_header_info() function. + * + * @var array + * @since Property available since Release 1.7.0 + */ + var $types = array( + 'C' => 'character', + 'D' => 'date', + 'L' => 'boolean', + 'M' => 'memo', + 'N' => 'number', + ); + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_dbase() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database and create it if it doesn't exist + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's dbase driver supports the following extra DSN options: + * + mode An integer specifying the read/write mode to use + * (0 = read only, 1 = write only, 2 = read/write). + * Available since PEAR DB 1.7.0. + * + fields An array of arrays that PHP's dbase_create() function needs + * to create a new database. This information is used if the + * dBase file specified in the "database" segment of the DSN + * does not exist. For more info, see the PHP manual's + * {@link http://php.net/dbase_create dbase_create()} page. + * Available since PEAR DB 1.7.0. + * + * Example of how to connect and establish a new dBase file if necessary: + * + * require_once 'DB.php'; + * + * $dsn = array( + * 'phptype' => 'dbase', + * 'database' => '/path/and/name/of/dbase/file', + * 'mode' => 2, + * 'fields' => array( + * array('a', 'N', 5, 0), + * array('b', 'C', 40), + * array('c', 'C', 255), + * array('d', 'C', 20), + * ), + * ); + * $options = array( + * 'debug' => 2, + * 'portability' => DB_PORTABILITY_ALL, + * ); + * + * $db = DB::connect($dsn, $options); + * if (PEAR::isError($db)) { + * die($db->getMessage()); + * } + * + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('dbase')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + /* + * Turn track_errors on for entire script since $php_errormsg + * is the only way to find errors from the dbase extension. + */ + @ini_set('track_errors', 1); + $php_errormsg = ''; + + if (!file_exists($dsn['database'])) { + $this->dsn['mode'] = 2; + if (empty($dsn['fields']) || !is_array($dsn['fields'])) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + 'the dbase file does not exist and ' + . 'it could not be created because ' + . 'the "fields" element of the DSN ' + . 'is not properly set'); + } + $this->connection = @dbase_create($dsn['database'], + $dsn['fields']); + if (!$this->connection) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + 'the dbase file does not exist and ' + . 'the attempt to create it failed: ' + . $php_errormsg); + } + } else { + if (!isset($this->dsn['mode'])) { + $this->dsn['mode'] = 0; + } + $this->connection = @dbase_open($dsn['database'], + $this->dsn['mode']); + if (!$this->connection) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $php_errormsg); + } + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @dbase_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ &query() + + function &query($query = null) + { + // emulate result resources + $this->res_row[(int)$this->result] = 0; + $tmp = new DB_result($this, $this->result++); + return $tmp; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum === null) { + $rownum = $this->res_row[(int)$result]++; + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @dbase_get_record_with_names($this->connection, $rownum); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @dbase_get_record($this->connection, $rownum); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set. + * + * This method is a no-op for dbase, as there aren't result resources in + * the same sense as most other database backends. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return true; + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($foo) + { + return @dbase_numfields($this->connection); + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($foo) + { + return @dbase_numrecords($this->connection); + } + + // }}} + // {{{ quoteBoolean() + + /** + * Formats a boolean value for use within a query in a locale-independent + * manner. + * + * @param boolean the boolean value to be quoted. + * @return string the quoted string. + * @see DB_common::quoteSmart() + * @since Method available since release 1.7.8. + */ + function quoteBoolean($boolean) { + return $boolean ? 'T' : 'F'; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about the current database + * + * @param mixed $result THIS IS UNUSED IN DBASE. The current database + * is examined regardless of what is provided here. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + * @since Method available since Release 1.7.0 + */ + function tableInfo($result = null, $mode = null) + { + if (function_exists('dbase_get_header_info')) { + $id = @dbase_get_header_info($this->connection); + if (!$id && $php_errormsg) { + return $this->raiseError(DB_ERROR, + null, null, null, + $php_errormsg); + } + } else { + /* + * This segment for PHP 4 is loosely based on code by + * Hadi Rusiah in the comments on + * the dBase reference page in the PHP manual. + */ + $db = @fopen($this->dsn['database'], 'r'); + if (!$db) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $php_errormsg); + } + + $id = array(); + $i = 0; + + $line = fread($db, 32); + while (!feof($db)) { + $line = fread($db, 32); + if (substr($line, 0, 1) == chr(13)) { + break; + } else { + $pos = strpos(substr($line, 0, 10), chr(0)); + $pos = ($pos == 0 ? 10 : $pos); + $id[$i] = array( + 'name' => substr($line, 0, $pos), + 'type' => $this->types[substr($line, 11, 1)], + 'length' => ord(substr($line, 16, 1)), + 'precision' => ord(substr($line, 17, 1)), + ); + } + $i++; + } + + fclose($db); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $res = array(); + $count = count($id); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => $this->dsn['database'], + 'name' => $case_func($id[$i]['name']), + 'type' => $id[$i]['type'], + 'len' => $id[$i]['length'], + 'flags' => '' + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + return $res; + } + + // }}} +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/fbsql.php b/common/PEAR/DB/fbsql.php new file mode 100644 index 0000000..a59b308 --- /dev/null +++ b/common/PEAR/DB/fbsql.php @@ -0,0 +1,769 @@ + + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: fbsql.php,v 1.88 2007/07/06 05:19:21 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's fbsql extension + * for interacting with FrontBase databases + * + * These methods overload the ones declared in DB_common. + * + * @category Database + * @package DB + * @author Frank M. Kromann + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + * @since Class functional since Release 1.7.0 + */ +class DB_fbsql extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'fbsql'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'fbsql'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'alter', + 'new_link' => false, + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => false, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + 22 => DB_ERROR_SYNTAX, + 85 => DB_ERROR_ALREADY_EXISTS, + 108 => DB_ERROR_SYNTAX, + 116 => DB_ERROR_NOSUCHTABLE, + 124 => DB_ERROR_VALUE_COUNT_ON_ROW, + 215 => DB_ERROR_NOSUCHFIELD, + 217 => DB_ERROR_INVALID_NUMBER, + 226 => DB_ERROR_NOSUCHFIELD, + 231 => DB_ERROR_INVALID, + 239 => DB_ERROR_TRUNCATED, + 251 => DB_ERROR_SYNTAX, + 266 => DB_ERROR_NOT_FOUND, + 357 => DB_ERROR_CONSTRAINT_NOT_NULL, + 358 => DB_ERROR_CONSTRAINT, + 360 => DB_ERROR_CONSTRAINT, + 361 => DB_ERROR_CONSTRAINT, + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_fbsql() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('fbsql')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $params = array( + $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost', + $dsn['username'] ? $dsn['username'] : null, + $dsn['password'] ? $dsn['password'] : null, + ); + + $connect_function = $persistent ? 'fbsql_pconnect' : 'fbsql_connect'; + + $ini = ini_get('track_errors'); + $php_errormsg = ''; + if ($ini) { + $this->connection = @call_user_func_array($connect_function, + $params); + } else { + @ini_set('track_errors', 1); + $this->connection = @call_user_func_array($connect_function, + $params); + @ini_set('track_errors', $ini); + } + + if (!$this->connection) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $php_errormsg); + } + + if ($dsn['database']) { + if (!@fbsql_select_db($dsn['database'], $this->connection)) { + return $this->fbsqlRaiseError(); + } + } + + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @fbsql_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $this->last_query = $query; + $query = $this->modifyQuery($query); + $result = @fbsql_query("$query;", $this->connection); + if (!$result) { + return $this->fbsqlRaiseError(); + } + // Determine which queries that should return data, and which + // should return an error code only. + if ($this->_checkManip($query)) { + return DB_OK; + } + return $result; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal fbsql result pointer to the next available result + * + * @param a valid fbsql result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return @fbsql_next_result($result); + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + if (!@fbsql_data_seek($result, $rownum)) { + return null; + } + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @fbsql_fetch_array($result, FBSQL_ASSOC); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @fbsql_fetch_row($result); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? fbsql_free_result($result) : false; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff=false) + { + if ($onoff) { + $this->query("SET COMMIT TRUE"); + } else { + $this->query("SET COMMIT FALSE"); + } + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + @fbsql_commit($this->connection); + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + @fbsql_rollback($this->connection); + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @fbsql_num_fields($result); + if (!$cols) { + return $this->fbsqlRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @fbsql_num_rows($result); + if ($rows === null) { + return $this->fbsqlRaiseError(); + } + return $rows; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if ($this->_last_query_manip) { + $result = @fbsql_affected_rows($this->connection); + } else { + $result = 0; + } + return $result; + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_fbsql::createSequence(), DB_fbsql::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + do { + $repeat = 0; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query('SELECT UNIQUE FROM ' . $seqname); + $this->popErrorHandling(); + if ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) { + $repeat = 1; + $result = $this->createSequence($seq_name); + if (DB::isError($result)) { + return $result; + } + } else { + $repeat = 0; + } + } while ($repeat); + if (DB::isError($result)) { + return $this->fbsqlRaiseError(); + } + $result->fetchInto($tmp, DB_FETCHMODE_ORDERED); + return $tmp[0]; + } + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_fbsql::nextID(), DB_fbsql::dropSequence() + */ + function createSequence($seq_name) + { + $seqname = $this->getSequenceName($seq_name); + $res = $this->query('CREATE TABLE ' . $seqname + . ' (id INTEGER NOT NULL,' + . ' PRIMARY KEY(id))'); + if ($res) { + $res = $this->query('SET UNIQUE = 0 FOR ' . $seqname); + } + return $res; + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_fbsql::nextID(), DB_fbsql::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name) + . ' RESTRICT'); + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + if (DB::isManip($query) || $this->_next_query_manip) { + return preg_replace('/^([\s(])*SELECT/i', + "\\1SELECT TOP($count)", $query); + } else { + return preg_replace('/([\s(])*SELECT/i', + "\\1SELECT TOP($from, $count)", $query); + } + } + + // }}} + // {{{ quoteBoolean() + + /** + * Formats a boolean value for use within a query in a locale-independent + * manner. + * + * @param boolean the boolean value to be quoted. + * @return string the quoted string. + * @see DB_common::quoteSmart() + * @since Method available since release 1.7.8. + */ + function quoteBoolean($boolean) { + return $boolean ? 'TRUE' : 'FALSE'; + } + + // }}} + // {{{ quoteFloat() + + /** + * Formats a float value for use within a query in a locale-independent + * manner. + * + * @param float the float value to be quoted. + * @return string the quoted string. + * @see DB_common::quoteSmart() + * @since Method available since release 1.7.8. + */ + function quoteFloat($float) { + return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); + } + + // }}} + // {{{ fbsqlRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_fbsql::errorNative(), DB_common::errorCode() + */ + function fbsqlRaiseError($errno = null) + { + if ($errno === null) { + $errno = $this->errorCode(fbsql_errno($this->connection)); + } + return $this->raiseError($errno, null, null, null, + @fbsql_error($this->connection)); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code produced by the last query + * + * @return int the DBMS' error code + */ + function errorNative() + { + return @fbsql_errno($this->connection); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @fbsql_list_fields($this->dsn['database'], + $result, $this->connection); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->fbsqlRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @fbsql_num_fields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => $case_func(@fbsql_field_table($id, $i)), + 'name' => $case_func(@fbsql_field_name($id, $i)), + 'type' => @fbsql_field_type($id, $i), + 'len' => @fbsql_field_len($id, $i), + 'flags' => @fbsql_field_flags($id, $i), + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @fbsql_free_result($id); + } + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return 'SELECT "table_name" FROM information_schema.tables' + . ' t0, information_schema.schemata t1' + . ' WHERE t0.schema_pk=t1.schema_pk AND' + . ' "table_type" = \'BASE TABLE\'' + . ' AND "schema_name" = current_schema'; + case 'views': + return 'SELECT "table_name" FROM information_schema.tables' + . ' t0, information_schema.schemata t1' + . ' WHERE t0.schema_pk=t1.schema_pk AND' + . ' "table_type" = \'VIEW\'' + . ' AND "schema_name" = current_schema'; + case 'users': + return 'SELECT "user_name" from information_schema.users'; + case 'functions': + return 'SELECT "routine_name" FROM' + . ' information_schema.psm_routines' + . ' t0, information_schema.schemata t1' + . ' WHERE t0.schema_pk=t1.schema_pk' + . ' AND "routine_kind"=\'FUNCTION\'' + . ' AND "schema_name" = current_schema'; + case 'procedures': + return 'SELECT "routine_name" FROM' + . ' information_schema.psm_routines' + . ' t0, information_schema.schemata t1' + . ' WHERE t0.schema_pk=t1.schema_pk' + . ' AND "routine_kind"=\'PROCEDURE\'' + . ' AND "schema_name" = current_schema'; + default: + return null; + } + } + + // }}} +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/ibase.php b/common/PEAR/DB/ibase.php new file mode 100644 index 0000000..f7af316 --- /dev/null +++ b/common/PEAR/DB/ibase.php @@ -0,0 +1,1082 @@ + + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: ibase.php,v 1.116 2007/09/21 13:40:41 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's interbase extension + * for interacting with Interbase and Firebird databases + * + * These methods overload the ones declared in DB_common. + * + * While this class works with PHP 4, PHP's InterBase extension is + * unstable in PHP 4. Use PHP 5. + * + * NOTICE: limitQuery() only works for Firebird. + * + * @category Database + * @package DB + * @author Sterling Hughes + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + * @since Class became stable in Release 1.7.0 + */ +class DB_ibase extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'ibase'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'ibase'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * NOTE: only firebird supports limit. + * + * @var array + */ + var $features = array( + 'limit' => false, + 'new_link' => false, + 'numrows' => 'emulate', + 'pconnect' => true, + 'prepare' => true, + 'ssl' => false, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + -104 => DB_ERROR_SYNTAX, + -150 => DB_ERROR_ACCESS_VIOLATION, + -151 => DB_ERROR_ACCESS_VIOLATION, + -155 => DB_ERROR_NOSUCHTABLE, + -157 => DB_ERROR_NOSUCHFIELD, + -158 => DB_ERROR_VALUE_COUNT_ON_ROW, + -170 => DB_ERROR_MISMATCH, + -171 => DB_ERROR_MISMATCH, + -172 => DB_ERROR_INVALID, + // -204 => // Covers too many errors, need to use regex on msg + -205 => DB_ERROR_NOSUCHFIELD, + -206 => DB_ERROR_NOSUCHFIELD, + -208 => DB_ERROR_INVALID, + -219 => DB_ERROR_NOSUCHTABLE, + -297 => DB_ERROR_CONSTRAINT, + -303 => DB_ERROR_INVALID, + -413 => DB_ERROR_INVALID_NUMBER, + -530 => DB_ERROR_CONSTRAINT, + -551 => DB_ERROR_ACCESS_VIOLATION, + -552 => DB_ERROR_ACCESS_VIOLATION, + // -607 => // Covers too many errors, need to use regex on msg + -625 => DB_ERROR_CONSTRAINT_NOT_NULL, + -803 => DB_ERROR_CONSTRAINT, + -804 => DB_ERROR_VALUE_COUNT_ON_ROW, + // -902 => // Covers too many errors, need to use regex on msg + -904 => DB_ERROR_CONNECT_FAILED, + -922 => DB_ERROR_NOSUCHDB, + -923 => DB_ERROR_CONNECT_FAILED, + -924 => DB_ERROR_CONNECT_FAILED + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * The number of rows affected by a data manipulation query + * @var integer + * @access private + */ + var $affected = 0; + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * The prepared statement handle from the most recently executed statement + * + * {@internal Mainly here because the InterBase/Firebird API is only + * able to retrieve data from result sets if the statemnt handle is + * still in scope.}} + * + * @var resource + */ + var $last_stmt; + + /** + * Is the given prepared statement a data manipulation query? + * @var array + * @access private + */ + var $manip_query = array(); + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_ibase() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's ibase driver supports the following extra DSN options: + * + buffers The number of database buffers to allocate for the + * server-side cache. + * + charset The default character set for a database. + * + dialect The default SQL dialect for any statement + * executed within a connection. Defaults to the + * highest one supported by client libraries. + * Functional only with InterBase 6 and up. + * + role Functional only with InterBase 5 and up. + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('interbase')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + if ($this->dbsyntax == 'firebird') { + $this->features['limit'] = 'alter'; + } + + $params = array( + $dsn['hostspec'] + ? ($dsn['hostspec'] . ':' . $dsn['database']) + : $dsn['database'], + $dsn['username'] ? $dsn['username'] : null, + $dsn['password'] ? $dsn['password'] : null, + isset($dsn['charset']) ? $dsn['charset'] : null, + isset($dsn['buffers']) ? $dsn['buffers'] : null, + isset($dsn['dialect']) ? $dsn['dialect'] : null, + isset($dsn['role']) ? $dsn['role'] : null, + ); + + $connect_function = $persistent ? 'ibase_pconnect' : 'ibase_connect'; + + $this->connection = @call_user_func_array($connect_function, $params); + if (!$this->connection) { + return $this->ibaseRaiseError(DB_ERROR_CONNECT_FAILED); + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @ibase_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = $this->_checkManip($query); + $this->last_query = $query; + $query = $this->modifyQuery($query); + $result = @ibase_query($this->connection, $query); + + if (!$result) { + return $this->ibaseRaiseError(); + } + if ($this->autocommit && $ismanip) { + @ibase_commit($this->connection); + } + if ($ismanip) { + $this->affected = $result; + return DB_OK; + } else { + $this->affected = 0; + return $result; + } + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * Only works with Firebird. + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + if ($this->dsn['dbsyntax'] == 'firebird') { + $query = preg_replace('/^([\s(])*SELECT/i', + "SELECT FIRST $count SKIP $from", $query); + } + return $query; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal ibase result pointer to the next available result + * + * @param a valid fbsql result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE); + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + if (function_exists('ibase_fetch_assoc')) { + $arr = @ibase_fetch_assoc($result); + } else { + $arr = get_object_vars(ibase_fetch_object($result)); + } + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @ibase_fetch_row($result); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? ibase_free_result($result) : false; + } + + // }}} + // {{{ freeQuery() + + function freeQuery($query) + { + return is_resource($query) ? ibase_free_query($query) : false; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if (is_integer($this->affected)) { + return $this->affected; + } + return $this->ibaseRaiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @ibase_num_fields($result); + if (!$cols) { + return $this->ibaseRaiseError(); + } + return $cols; + } + + // }}} + // {{{ prepare() + + /** + * Prepares a query for multiple execution with execute(). + * + * prepare() requires a generic query as string like + * INSERT INTO numbers VALUES (?, ?, ?) + * . The ? characters are placeholders. + * + * Three types of placeholders can be used: + * + ? a quoted scalar value, i.e. strings, integers + * + ! value is inserted 'as is' + * + & requires a file name. The file's contents get + * inserted into the query (i.e. saving binary + * data in a db) + * + * Use backslashes to escape placeholder characters if you don't want + * them to be interpreted as placeholders. Example: + * "UPDATE foo SET col=? WHERE col='over \& under'" + * + * + * @param string $query query to be prepared + * @return mixed DB statement resource on success. DB_Error on failure. + */ + function prepare($query) + { + $tokens = preg_split('/((? $val) { + switch ($val) { + case '?': + $types[$token++] = DB_PARAM_SCALAR; + break; + case '&': + $types[$token++] = DB_PARAM_OPAQUE; + break; + case '!': + $types[$token++] = DB_PARAM_MISC; + break; + default: + $tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val); + $newquery .= $tokens[$key] . '?'; + } + } + + $newquery = substr($newquery, 0, -1); + $this->last_query = $query; + $newquery = $this->modifyQuery($newquery); + $stmt = @ibase_prepare($this->connection, $newquery); + + if ($stmt === false) { + $stmt = $this->ibaseRaiseError(); + } else { + $this->prepare_types[(int)$stmt] = $types; + $this->manip_query[(int)$stmt] = DB::isManip($query); + } + + return $stmt; + } + + // }}} + // {{{ execute() + + /** + * Executes a DB statement prepared with prepare(). + * + * @param resource $stmt a DB statement resource returned from prepare() + * @param mixed $data array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 for non-array items or the + * quantity of elements in the array. + * @return object a new DB_Result or a DB_Error when fail + * @see DB_ibase::prepare() + * @access public + */ + function &execute($stmt, $data = array()) + { + $data = (array)$data; + $this->last_parameters = $data; + + $types = $this->prepare_types[(int)$stmt]; + if (count($types) != count($data)) { + $tmp = $this->raiseError(DB_ERROR_MISMATCH); + return $tmp; + } + + $i = 0; + foreach ($data as $key => $value) { + if ($types[$i] == DB_PARAM_MISC) { + /* + * ibase doesn't seem to have the ability to pass a + * parameter along unchanged, so strip off quotes from start + * and end, plus turn two single quotes to one single quote, + * in order to avoid the quotes getting escaped by + * ibase and ending up in the database. + */ + $data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]); + $data[$key] = str_replace("''", "'", $data[$key]); + } elseif ($types[$i] == DB_PARAM_OPAQUE) { + $fp = @fopen($data[$key], 'rb'); + if (!$fp) { + $tmp = $this->raiseError(DB_ERROR_ACCESS_VIOLATION); + return $tmp; + } + $data[$key] = fread($fp, filesize($data[$key])); + fclose($fp); + } + $i++; + } + + array_unshift($data, $stmt); + + $res = call_user_func_array('ibase_execute', $data); + if (!$res) { + $tmp = $this->ibaseRaiseError(); + return $tmp; + } + /* XXX need this? + if ($this->autocommit && $this->manip_query[(int)$stmt]) { + @ibase_commit($this->connection); + }*/ + $this->last_stmt = $stmt; + if ($this->manip_query[(int)$stmt] || $this->_next_query_manip) { + $this->_last_query_manip = true; + $this->_next_query_manip = false; + $tmp = DB_OK; + } else { + $this->_last_query_manip = false; + $tmp = new DB_result($this, $res); + } + return $tmp; + } + + /** + * Frees the internal resources associated with a prepared query + * + * @param resource $stmt the prepared statement's PHP resource + * @param bool $free_resource should the PHP resource be freed too? + * Use false if you need to get data + * from the result set later. + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_ibase::prepare() + */ + function freePrepared($stmt, $free_resource = true) + { + if (!is_resource($stmt)) { + return false; + } + if ($free_resource) { + @ibase_free_query($stmt); + } + unset($this->prepare_tokens[(int)$stmt]); + unset($this->prepare_types[(int)$stmt]); + unset($this->manip_query[(int)$stmt]); + return true; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + $this->autocommit = $onoff ? 1 : 0; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + return @ibase_commit($this->connection); + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + return @ibase_rollback($this->connection); + } + + // }}} + // {{{ transactionInit() + + function transactionInit($trans_args = 0) + { + return $trans_args + ? @ibase_trans($trans_args, $this->connection) + : @ibase_trans(); + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_ibase::createSequence(), DB_ibase::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $sqn = strtoupper($this->getSequenceName($seq_name)); + $repeat = 0; + do { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("SELECT GEN_ID(${sqn}, 1) " + . 'FROM RDB$GENERATORS ' + . "WHERE RDB\$GENERATOR_NAME='${sqn}'"); + $this->popErrorHandling(); + if ($ondemand && DB::isError($result)) { + $repeat = 1; + $result = $this->createSequence($seq_name); + if (DB::isError($result)) { + return $result; + } + } else { + $repeat = 0; + } + } while ($repeat); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $arr = $result->fetchRow(DB_FETCHMODE_ORDERED); + $result->free(); + return $arr[0]; + } + + // }}} + // {{{ createSequence() + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_ibase::nextID(), DB_ibase::dropSequence() + */ + function createSequence($seq_name) + { + $sqn = strtoupper($this->getSequenceName($seq_name)); + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("CREATE GENERATOR ${sqn}"); + $this->popErrorHandling(); + + return $result; + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_ibase::nextID(), DB_ibase::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DELETE FROM RDB$GENERATORS ' + . "WHERE RDB\$GENERATOR_NAME='" + . strtoupper($this->getSequenceName($seq_name)) + . "'"); + } + + // }}} + // {{{ _ibaseFieldFlags() + + /** + * Get the column's flags + * + * Supports "primary_key", "unique_key", "not_null", "default", + * "computed" and "blob". + * + * @param string $field_name the name of the field + * @param string $table_name the name of the table + * + * @return string the flags + * + * @access private + */ + function _ibaseFieldFlags($field_name, $table_name) + { + $sql = 'SELECT R.RDB$CONSTRAINT_TYPE CTYPE' + .' FROM RDB$INDEX_SEGMENTS I' + .' JOIN RDB$RELATION_CONSTRAINTS R ON I.RDB$INDEX_NAME=R.RDB$INDEX_NAME' + .' WHERE I.RDB$FIELD_NAME=\'' . $field_name . '\'' + .' AND UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\''; + + $result = @ibase_query($this->connection, $sql); + if (!$result) { + return $this->ibaseRaiseError(); + } + + $flags = ''; + if ($obj = @ibase_fetch_object($result)) { + @ibase_free_result($result); + if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'PRIMARY KEY') { + $flags .= 'primary_key '; + } + if (isset($obj->CTYPE) && trim($obj->CTYPE) == 'UNIQUE') { + $flags .= 'unique_key '; + } + } + + $sql = 'SELECT R.RDB$NULL_FLAG AS NFLAG,' + .' R.RDB$DEFAULT_SOURCE AS DSOURCE,' + .' F.RDB$FIELD_TYPE AS FTYPE,' + .' F.RDB$COMPUTED_SOURCE AS CSOURCE' + .' FROM RDB$RELATION_FIELDS R ' + .' JOIN RDB$FIELDS F ON R.RDB$FIELD_SOURCE=F.RDB$FIELD_NAME' + .' WHERE UPPER(R.RDB$RELATION_NAME)=\'' . strtoupper($table_name) . '\'' + .' AND R.RDB$FIELD_NAME=\'' . $field_name . '\''; + + $result = @ibase_query($this->connection, $sql); + if (!$result) { + return $this->ibaseRaiseError(); + } + if ($obj = @ibase_fetch_object($result)) { + @ibase_free_result($result); + if (isset($obj->NFLAG)) { + $flags .= 'not_null '; + } + if (isset($obj->DSOURCE)) { + $flags .= 'default '; + } + if (isset($obj->CSOURCE)) { + $flags .= 'computed '; + } + if (isset($obj->FTYPE) && $obj->FTYPE == 261) { + $flags .= 'blob '; + } + } + + return trim($flags); + } + + // }}} + // {{{ ibaseRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_ibase::errorNative(), DB_ibase::errorCode() + */ + function &ibaseRaiseError($errno = null) + { + if ($errno === null) { + $errno = $this->errorCode($this->errorNative()); + } + $tmp = $this->raiseError($errno, null, null, null, @ibase_errmsg()); + return $tmp; + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code produced by the last query + * + * @return int the DBMS' error code. NULL if there is no error code. + * + * @since Method available since Release 1.7.0 + */ + function errorNative() + { + if (function_exists('ibase_errcode')) { + return @ibase_errcode(); + } + if (preg_match('/^Dynamic SQL Error SQL error code = ([0-9-]+)/i', + @ibase_errmsg(), $m)) { + return (int)$m[1]; + } + return null; + } + + // }}} + // {{{ errorCode() + + /** + * Maps native error codes to DB's portable ones + * + * @param int $nativecode the error code returned by the DBMS + * + * @return int the portable DB error code. Return DB_ERROR if the + * current driver doesn't have a mapping for the + * $nativecode submitted. + * + * @since Method available since Release 1.7.0 + */ + function errorCode($nativecode = null) + { + if (isset($this->errorcode_map[$nativecode])) { + return $this->errorcode_map[$nativecode]; + } + + static $error_regexps; + if (!isset($error_regexps)) { + $error_regexps = array( + '/generator .* is not defined/' + => DB_ERROR_SYNTAX, // for compat. w ibase_errcode() + '/table.*(not exist|not found|unknown)/i' + => DB_ERROR_NOSUCHTABLE, + '/table .* already exists/i' + => DB_ERROR_ALREADY_EXISTS, + '/unsuccessful metadata update .* failed attempt to store duplicate value/i' + => DB_ERROR_ALREADY_EXISTS, + '/unsuccessful metadata update .* not found/i' + => DB_ERROR_NOT_FOUND, + '/validation error for column .* value "\*\*\* null/i' + => DB_ERROR_CONSTRAINT_NOT_NULL, + '/violation of [\w ]+ constraint/i' + => DB_ERROR_CONSTRAINT, + '/conversion error from string/i' + => DB_ERROR_INVALID_NUMBER, + '/no permission for/i' + => DB_ERROR_ACCESS_VIOLATION, + '/arithmetic exception, numeric overflow, or string truncation/i' + => DB_ERROR_INVALID, + '/feature is not supported/i' + => DB_ERROR_NOT_CAPABLE, + ); + } + + $errormsg = @ibase_errmsg(); + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $errormsg)) { + return $code; + } + } + return DB_ERROR; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @ibase_query($this->connection, + "SELECT * FROM $result WHERE 1=0"); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->ibaseRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @ibase_num_fields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $info = @ibase_field_info($id, $i); + $res[$i] = array( + 'table' => $got_string ? $case_func($result) : '', + 'name' => $case_func($info['name']), + 'type' => $info['type'], + 'len' => $info['length'], + 'flags' => ($got_string) + ? $this->_ibaseFieldFlags($info['name'], $result) + : '', + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @ibase_free_result($id); + } + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return 'SELECT DISTINCT R.RDB$RELATION_NAME FROM ' + . 'RDB$RELATION_FIELDS R WHERE R.RDB$SYSTEM_FLAG=0'; + case 'views': + return 'SELECT DISTINCT RDB$VIEW_NAME from RDB$VIEW_RELATIONS'; + case 'users': + return 'SELECT DISTINCT RDB$USER FROM RDB$USER_PRIVILEGES'; + default: + return null; + } + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/ifx.php b/common/PEAR/DB/ifx.php new file mode 100644 index 0000000..3e36794 --- /dev/null +++ b/common/PEAR/DB/ifx.php @@ -0,0 +1,683 @@ + + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: ifx.php,v 1.75 2007/07/06 05:19:21 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's ifx extension + * for interacting with Informix databases + * + * These methods overload the ones declared in DB_common. + * + * More info on Informix errors can be found at: + * http://www.informix.com/answers/english/ierrors.htm + * + * TODO: + * - set needed env Informix vars on connect + * - implement native prepare/execute + * + * @category Database + * @package DB + * @author Tomas V.V.Cox + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_ifx extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'ifx'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'ifx'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'emulate', + 'new_link' => false, + 'numrows' => 'emulate', + 'pconnect' => true, + 'prepare' => false, + 'ssl' => false, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + '-201' => DB_ERROR_SYNTAX, + '-206' => DB_ERROR_NOSUCHTABLE, + '-217' => DB_ERROR_NOSUCHFIELD, + '-236' => DB_ERROR_VALUE_COUNT_ON_ROW, + '-239' => DB_ERROR_CONSTRAINT, + '-253' => DB_ERROR_SYNTAX, + '-268' => DB_ERROR_CONSTRAINT, + '-292' => DB_ERROR_CONSTRAINT_NOT_NULL, + '-310' => DB_ERROR_ALREADY_EXISTS, + '-316' => DB_ERROR_ALREADY_EXISTS, + '-319' => DB_ERROR_NOT_FOUND, + '-329' => DB_ERROR_NODBSELECTED, + '-346' => DB_ERROR_CONSTRAINT, + '-386' => DB_ERROR_CONSTRAINT_NOT_NULL, + '-391' => DB_ERROR_CONSTRAINT_NOT_NULL, + '-554' => DB_ERROR_SYNTAX, + '-691' => DB_ERROR_CONSTRAINT, + '-692' => DB_ERROR_CONSTRAINT, + '-703' => DB_ERROR_CONSTRAINT_NOT_NULL, + '-1202' => DB_ERROR_DIVZERO, + '-1204' => DB_ERROR_INVALID_DATE, + '-1205' => DB_ERROR_INVALID_DATE, + '-1206' => DB_ERROR_INVALID_DATE, + '-1209' => DB_ERROR_INVALID_DATE, + '-1210' => DB_ERROR_INVALID_DATE, + '-1212' => DB_ERROR_INVALID_DATE, + '-1213' => DB_ERROR_INVALID_NUMBER, + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * The quantity of transactions begun + * + * {@internal While this is private, it can't actually be designated + * private in PHP 5 because it is directly accessed in the test suite.}} + * + * @var integer + * @access private + */ + var $transaction_opcount = 0; + + /** + * The number of rows affected by a data manipulation query + * @var integer + * @access private + */ + var $affected = 0; + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_ifx() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('informix') && + !PEAR::loadExtension('Informix')) + { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $dbhost = $dsn['hostspec'] ? '@' . $dsn['hostspec'] : ''; + $dbname = $dsn['database'] ? $dsn['database'] . $dbhost : ''; + $user = $dsn['username'] ? $dsn['username'] : ''; + $pw = $dsn['password'] ? $dsn['password'] : ''; + + $connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect'; + + $this->connection = @$connect_function($dbname, $user, $pw); + if (!is_resource($this->connection)) { + return $this->ifxRaiseError(DB_ERROR_CONNECT_FAILED); + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @ifx_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = $this->_checkManip($query); + $this->last_query = $query; + $this->affected = null; + if (preg_match('/(SELECT|EXECUTE)/i', $query)) { //TESTME: Use !DB::isManip()? + // the scroll is needed for fetching absolute row numbers + // in a select query result + $result = @ifx_query($query, $this->connection, IFX_SCROLL); + } else { + if (!$this->autocommit && $ismanip) { + if ($this->transaction_opcount == 0) { + $result = @ifx_query('BEGIN WORK', $this->connection); + if (!$result) { + return $this->ifxRaiseError(); + } + } + $this->transaction_opcount++; + } + $result = @ifx_query($query, $this->connection); + } + if (!$result) { + return $this->ifxRaiseError(); + } + $this->affected = @ifx_affected_rows($result); + // Determine which queries should return data, and which + // should return an error code only. + if (preg_match('/(SELECT|EXECUTE)/i', $query)) { + return $result; + } + // XXX Testme: free results inside a transaction + // may cause to stop it and commit the work? + + // Result has to be freed even with a insert or update + @ifx_free_result($result); + + return DB_OK; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal ifx result pointer to the next available result + * + * @param a valid fbsql result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if ($this->_last_query_manip) { + return $this->affected; + } else { + return 0; + } + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if (($rownum !== null) && ($rownum < 0)) { + return null; + } + if ($rownum === null) { + /* + * Even though fetch_row() should return the next row if + * $rownum is null, it doesn't in all cases. Bug 598. + */ + $rownum = 'NEXT'; + } else { + // Index starts at row 1, unlike most DBMS's starting at 0. + $rownum++; + } + if (!$arr = @ifx_fetch_row($result, $rownum)) { + return null; + } + if ($fetchmode !== DB_FETCHMODE_ASSOC) { + $i=0; + $order = array(); + foreach ($arr as $val) { + $order[$i++] = $val; + } + $arr = $order; + } elseif ($fetchmode == DB_FETCHMODE_ASSOC && + $this->options['portability'] & DB_PORTABILITY_LOWERCASE) + { + $arr = array_change_key_case($arr, CASE_LOWER); + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + if (!$cols = @ifx_num_fields($result)) { + return $this->ifxRaiseError(); + } + return $cols; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? ifx_free_result($result) : false; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = true) + { + // XXX if $this->transaction_opcount > 0, we should probably + // issue a warning here. + $this->autocommit = $onoff ? true : false; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + if ($this->transaction_opcount > 0) { + $result = @ifx_query('COMMIT WORK', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->ifxRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + if ($this->transaction_opcount > 0) { + $result = @ifx_query('ROLLBACK WORK', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->ifxRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ ifxRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_ifx::errorNative(), DB_ifx::errorCode() + */ + function ifxRaiseError($errno = null) + { + if ($errno === null) { + $errno = $this->errorCode(ifx_error()); + } + return $this->raiseError($errno, null, null, null, + $this->errorNative()); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code and message produced by the last query + * + * @return string the DBMS' error code and message + */ + function errorNative() + { + return @ifx_error() . ' ' . @ifx_errormsg(); + } + + // }}} + // {{{ errorCode() + + /** + * Maps native error codes to DB's portable ones. + * + * Requires that the DB implementation's constructor fills + * in the $errorcode_map property. + * + * @param string $nativecode error code returned by the database + * @return int a portable DB error code, or DB_ERROR if this DB + * implementation has no mapping for the given error code. + */ + function errorCode($nativecode) + { + if (ereg('SQLCODE=(.*)]', $nativecode, $match)) { + $code = $match[1]; + if (isset($this->errorcode_map[$code])) { + return $this->errorcode_map[$code]; + } + } + return DB_ERROR; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' if $result is a table name. + * + * If analyzing a query result and the result has duplicate field names, + * an error will be raised saying + * can't distinguish duplicate field names. + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + * @since Method available since Release 1.6.0 + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @ifx_query("SELECT * FROM $result WHERE 1=0", + $this->connection); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + $flds = @ifx_fieldproperties($id); + $count = @ifx_num_fields($id); + + if (count($flds) != $count) { + return $this->raiseError("can't distinguish duplicate field names"); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $i = 0; + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + foreach ($flds as $key => $value) { + $props = explode(';', $value); + $res[$i] = array( + 'table' => $got_string ? $case_func($result) : '', + 'name' => $case_func($key), + 'type' => $props[0], + 'len' => $props[1], + 'flags' => $props[4] == 'N' ? 'not_null' : '', + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + $i++; + } + + // free the result only if we were called on a table + if ($got_string) { + @ifx_free_result($id); + } + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return 'SELECT tabname FROM systables WHERE tabid >= 100'; + default: + return null; + } + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/msql.php b/common/PEAR/DB/msql.php new file mode 100644 index 0000000..4314f28 --- /dev/null +++ b/common/PEAR/DB/msql.php @@ -0,0 +1,831 @@ + + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: msql.php,v 1.64 2007/09/21 13:40:41 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's msql extension + * for interacting with Mini SQL databases + * + * These methods overload the ones declared in DB_common. + * + * PHP's mSQL extension did weird things with NULL values prior to PHP + * 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds + * those versions. + * + * @category Database + * @package DB + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + * @since Class not functional until Release 1.7.0 + */ +class DB_msql extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'msql'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'msql'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'emulate', + 'new_link' => false, + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => false, + 'transactions' => false, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * The query result resource created by PHP + * + * Used to make affectedRows() work. Only contains the result for + * data manipulation queries. Contains false for other queries. + * + * @var resource + * @access private + */ + var $_result; + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_msql() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * Example of how to connect: + * + * require_once 'DB.php'; + * + * // $dsn = 'msql://hostname/dbname'; // use a TCP connection + * $dsn = 'msql:///dbname'; // use a socket + * $options = array( + * 'portability' => DB_PORTABILITY_ALL, + * ); + * + * $db = DB::connect($dsn, $options); + * if (PEAR::isError($db)) { + * die($db->getMessage()); + * } + * + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('msql')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $params = array(); + if ($dsn['hostspec']) { + $params[] = $dsn['port'] + ? $dsn['hostspec'] . ',' . $dsn['port'] + : $dsn['hostspec']; + } + + $connect_function = $persistent ? 'msql_pconnect' : 'msql_connect'; + + $ini = ini_get('track_errors'); + $php_errormsg = ''; + if ($ini) { + $this->connection = @call_user_func_array($connect_function, + $params); + } else { + @ini_set('track_errors', 1); + $this->connection = @call_user_func_array($connect_function, + $params); + @ini_set('track_errors', $ini); + } + + if (!$this->connection) { + if (($err = @msql_error()) != '') { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $err); + } else { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $php_errormsg); + } + } + + if (!@msql_select_db($dsn['database'], $this->connection)) { + return $this->msqlRaiseError(); + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @msql_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $this->last_query = $query; + $query = $this->modifyQuery($query); + $result = @msql_query($query, $this->connection); + if (!$result) { + return $this->msqlRaiseError(); + } + // Determine which queries that should return data, and which + // should return an error code only. + if ($this->_checkManip($query)) { + $this->_result = $result; + return DB_OK; + } else { + $this->_result = false; + return $result; + } + } + + + // }}} + // {{{ nextResult() + + /** + * Move the internal msql result pointer to the next available result + * + * @param a valid fbsql result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * PHP's mSQL extension did weird things with NULL values prior to PHP + * 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds + * those versions. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + if (!@msql_data_seek($result, $rownum)) { + return null; + } + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @msql_fetch_array($result, MSQL_ASSOC); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @msql_fetch_row($result); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? msql_free_result($result) : false; + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @msql_num_fields($result); + if (!$cols) { + return $this->msqlRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @msql_num_rows($result); + if ($rows === false) { + return $this->msqlRaiseError(); + } + return $rows; + } + + // }}} + // {{{ affected() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if (!$this->_result) { + return 0; + } + return msql_affected_rows($this->_result); + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_msql::createSequence(), DB_msql::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + $repeat = false; + do { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("SELECT _seq FROM ${seqname}"); + $this->popErrorHandling(); + if ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) { + $repeat = true; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->createSequence($seq_name); + $this->popErrorHandling(); + if (DB::isError($result)) { + return $this->raiseError($result); + } + } else { + $repeat = false; + } + } while ($repeat); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $arr = $result->fetchRow(DB_FETCHMODE_ORDERED); + $result->free(); + return $arr[0]; + } + + // }}} + // {{{ createSequence() + + /** + * Creates a new sequence + * + * Also creates a new table to associate the sequence with. Uses + * a separate table to ensure portability with other drivers. + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_msql::nextID(), DB_msql::dropSequence() + */ + function createSequence($seq_name) + { + $seqname = $this->getSequenceName($seq_name); + $res = $this->query('CREATE TABLE ' . $seqname + . ' (id INTEGER NOT NULL)'); + if (DB::isError($res)) { + return $res; + } + $res = $this->query("CREATE SEQUENCE ON ${seqname}"); + return $res; + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_msql::nextID(), DB_msql::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ quoteIdentifier() + + /** + * mSQL does not support delimited identifiers + * + * @param string $str the identifier name to be quoted + * + * @return object a DB_Error object + * + * @see DB_common::quoteIdentifier() + * @since Method available since Release 1.7.0 + */ + function quoteIdentifier($str) + { + return $this->raiseError(DB_ERROR_UNSUPPORTED); + } + + // }}} + // {{{ quoteFloat() + + /** + * Formats a float value for use within a query in a locale-independent + * manner. + * + * @param float the float value to be quoted. + * @return string the quoted string. + * @see DB_common::quoteSmart() + * @since Method available since release 1.7.8. + */ + function quoteFloat($float) { + return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); + } + + // }}} + // {{{ escapeSimple() + + /** + * Escapes a string according to the current DBMS's standards + * + * @param string $str the string to be escaped + * + * @return string the escaped string + * + * @see DB_common::quoteSmart() + * @since Method available since Release 1.7.0 + */ + function escapeSimple($str) + { + return addslashes($str); + } + + // }}} + // {{{ msqlRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_msql::errorNative(), DB_msql::errorCode() + */ + function msqlRaiseError($errno = null) + { + $native = $this->errorNative(); + if ($errno === null) { + $errno = $this->errorCode($native); + } + return $this->raiseError($errno, null, null, null, $native); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error message produced by the last query + * + * @return string the DBMS' error message + */ + function errorNative() + { + return @msql_error(); + } + + // }}} + // {{{ errorCode() + + /** + * Determines PEAR::DB error code from the database's text error message + * + * @param string $errormsg the error message returned from the database + * + * @return integer the error number from a DB_ERROR* constant + */ + function errorCode($errormsg) + { + static $error_regexps; + + // PHP 5.2+ prepends the function name to $php_errormsg, so we need + // this hack to work around it, per bug #9599. + $errormsg = preg_replace('/^msql[a-z_]+\(\): /', '', $errormsg); + + if (!isset($error_regexps)) { + $error_regexps = array( + '/^Access to database denied/i' + => DB_ERROR_ACCESS_VIOLATION, + '/^Bad index name/i' + => DB_ERROR_ALREADY_EXISTS, + '/^Bad order field/i' + => DB_ERROR_SYNTAX, + '/^Bad type for comparison/i' + => DB_ERROR_SYNTAX, + '/^Can\'t perform LIKE on/i' + => DB_ERROR_SYNTAX, + '/^Can\'t use TEXT fields in LIKE comparison/i' + => DB_ERROR_SYNTAX, + '/^Couldn\'t create temporary table/i' + => DB_ERROR_CANNOT_CREATE, + '/^Error creating table file/i' + => DB_ERROR_CANNOT_CREATE, + '/^Field .* cannot be null$/i' + => DB_ERROR_CONSTRAINT_NOT_NULL, + '/^Index (field|condition) .* cannot be null$/i' + => DB_ERROR_SYNTAX, + '/^Invalid date format/i' + => DB_ERROR_INVALID_DATE, + '/^Invalid time format/i' + => DB_ERROR_INVALID, + '/^Literal value for .* is wrong type$/i' + => DB_ERROR_INVALID_NUMBER, + '/^No Database Selected/i' + => DB_ERROR_NODBSELECTED, + '/^No value specified for field/i' + => DB_ERROR_VALUE_COUNT_ON_ROW, + '/^Non unique value for unique index/i' + => DB_ERROR_CONSTRAINT, + '/^Out of memory for temporary table/i' + => DB_ERROR_CANNOT_CREATE, + '/^Permission denied/i' + => DB_ERROR_ACCESS_VIOLATION, + '/^Reference to un-selected table/i' + => DB_ERROR_SYNTAX, + '/^syntax error/i' + => DB_ERROR_SYNTAX, + '/^Table .* exists$/i' + => DB_ERROR_ALREADY_EXISTS, + '/^Unknown database/i' + => DB_ERROR_NOSUCHDB, + '/^Unknown field/i' + => DB_ERROR_NOSUCHFIELD, + '/^Unknown (index|system variable)/i' + => DB_ERROR_NOT_FOUND, + '/^Unknown table/i' + => DB_ERROR_NOSUCHTABLE, + '/^Unqualified field/i' + => DB_ERROR_SYNTAX, + ); + } + + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $errormsg)) { + return $code; + } + } + return DB_ERROR; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::setOption() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @msql_query("SELECT * FROM $result", + $this->connection); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->raiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @msql_num_fields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $tmp = @msql_fetch_field($id); + + $flags = ''; + if ($tmp->not_null) { + $flags .= 'not_null '; + } + if ($tmp->unique) { + $flags .= 'unique_key '; + } + $flags = trim($flags); + + $res[$i] = array( + 'table' => $case_func($tmp->table), + 'name' => $case_func($tmp->name), + 'type' => $tmp->type, + 'len' => msql_field_len($id, $i), + 'flags' => $flags, + ); + + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @msql_free_result($id); + } + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtain a list of a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return array the array containing the list of objects requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'databases': + $id = @msql_list_dbs($this->connection); + break; + case 'tables': + $id = @msql_list_tables($this->dsn['database'], + $this->connection); + break; + default: + return null; + } + if (!$id) { + return $this->msqlRaiseError(); + } + $out = array(); + while ($row = @msql_fetch_row($id)) { + $out[] = $row[0]; + } + return $out; + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/mssql.php b/common/PEAR/DB/mssql.php new file mode 100644 index 0000000..68a151a --- /dev/null +++ b/common/PEAR/DB/mssql.php @@ -0,0 +1,963 @@ + + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: mssql.php,v 1.92 2007/09/21 13:40:41 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's mssql extension + * for interacting with Microsoft SQL Server databases + * + * These methods overload the ones declared in DB_common. + * + * DB's mssql driver is only for Microsfoft SQL Server databases. + * + * If you're connecting to a Sybase database, you MUST specify "sybase" + * as the "phptype" in the DSN. + * + * This class only works correctly if you have compiled PHP using + * --with-mssql=[dir_to_FreeTDS]. + * + * @category Database + * @package DB + * @author Sterling Hughes + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_mssql extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'mssql'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'mssql'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'emulate', + 'new_link' => false, + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => false, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + // XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX + var $errorcode_map = array( + 102 => DB_ERROR_SYNTAX, + 110 => DB_ERROR_VALUE_COUNT_ON_ROW, + 155 => DB_ERROR_NOSUCHFIELD, + 156 => DB_ERROR_SYNTAX, + 170 => DB_ERROR_SYNTAX, + 207 => DB_ERROR_NOSUCHFIELD, + 208 => DB_ERROR_NOSUCHTABLE, + 245 => DB_ERROR_INVALID_NUMBER, + 319 => DB_ERROR_SYNTAX, + 321 => DB_ERROR_NOSUCHFIELD, + 325 => DB_ERROR_SYNTAX, + 336 => DB_ERROR_SYNTAX, + 515 => DB_ERROR_CONSTRAINT_NOT_NULL, + 547 => DB_ERROR_CONSTRAINT, + 1018 => DB_ERROR_SYNTAX, + 1035 => DB_ERROR_SYNTAX, + 1913 => DB_ERROR_ALREADY_EXISTS, + 2209 => DB_ERROR_SYNTAX, + 2223 => DB_ERROR_SYNTAX, + 2248 => DB_ERROR_SYNTAX, + 2256 => DB_ERROR_SYNTAX, + 2257 => DB_ERROR_SYNTAX, + 2627 => DB_ERROR_CONSTRAINT, + 2714 => DB_ERROR_ALREADY_EXISTS, + 3607 => DB_ERROR_DIVZERO, + 3701 => DB_ERROR_NOSUCHTABLE, + 7630 => DB_ERROR_SYNTAX, + 8134 => DB_ERROR_DIVZERO, + 9303 => DB_ERROR_SYNTAX, + 9317 => DB_ERROR_SYNTAX, + 9318 => DB_ERROR_SYNTAX, + 9331 => DB_ERROR_SYNTAX, + 9332 => DB_ERROR_SYNTAX, + 15253 => DB_ERROR_SYNTAX, + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * The quantity of transactions begun + * + * {@internal While this is private, it can't actually be designated + * private in PHP 5 because it is directly accessed in the test suite.}} + * + * @var integer + * @access private + */ + var $transaction_opcount = 0; + + /** + * The database specified in the DSN + * + * It's a fix to allow calls to different databases in the same script. + * + * @var string + * @access private + */ + var $_db = null; + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_mssql() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('mssql') && !PEAR::loadExtension('sybase') + && !PEAR::loadExtension('sybase_ct')) + { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $params = array( + $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost', + $dsn['username'] ? $dsn['username'] : null, + $dsn['password'] ? $dsn['password'] : null, + ); + if ($dsn['port']) { + $params[0] .= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':') + . $dsn['port']; + } + + $connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect'; + + $this->connection = @call_user_func_array($connect_function, $params); + + if (!$this->connection) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + @mssql_get_last_message()); + } + if ($dsn['database']) { + if (!@mssql_select_db($dsn['database'], $this->connection)) { + return $this->raiseError(DB_ERROR_NODBSELECTED, + null, null, null, + @mssql_get_last_message()); + } + $this->_db = $dsn['database']; + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @mssql_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = $this->_checkManip($query); + $this->last_query = $query; + if (!@mssql_select_db($this->_db, $this->connection)) { + return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); + } + $query = $this->modifyQuery($query); + if (!$this->autocommit && $ismanip) { + if ($this->transaction_opcount == 0) { + $result = @mssql_query('BEGIN TRAN', $this->connection); + if (!$result) { + return $this->mssqlRaiseError(); + } + } + $this->transaction_opcount++; + } + $result = @mssql_query($query, $this->connection); + if (!$result) { + return $this->mssqlRaiseError(); + } + // Determine which queries that should return data, and which + // should return an error code only. + return $ismanip ? DB_OK : $result; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal mssql result pointer to the next available result + * + * @param a valid fbsql result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return @mssql_next_result($result); + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + if (!@mssql_data_seek($result, $rownum)) { + return null; + } + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @mssql_fetch_assoc($result); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @mssql_fetch_row($result); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? mssql_free_result($result) : false; + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @mssql_num_fields($result); + if (!$cols) { + return $this->mssqlRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @mssql_num_rows($result); + if ($rows === false) { + return $this->mssqlRaiseError(); + } + return $rows; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + // XXX if $this->transaction_opcount > 0, we should probably + // issue a warning here. + $this->autocommit = $onoff ? true : false; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + if ($this->transaction_opcount > 0) { + if (!@mssql_select_db($this->_db, $this->connection)) { + return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); + } + $result = @mssql_query('COMMIT TRAN', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->mssqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + if ($this->transaction_opcount > 0) { + if (!@mssql_select_db($this->_db, $this->connection)) { + return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); + } + $result = @mssql_query('ROLLBACK TRAN', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->mssqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if ($this->_last_query_manip) { + $res = @mssql_query('select @@rowcount', $this->connection); + if (!$res) { + return $this->mssqlRaiseError(); + } + $ar = @mssql_fetch_row($res); + if (!$ar) { + $result = 0; + } else { + @mssql_free_result($res); + $result = $ar[0]; + } + } else { + $result = 0; + } + return $result; + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_mssql::createSequence(), DB_mssql::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + if (!@mssql_select_db($this->_db, $this->connection)) { + return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); + } + $repeat = 0; + do { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)"); + $this->popErrorHandling(); + if ($ondemand && DB::isError($result) && + ($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE)) + { + $repeat = 1; + $result = $this->createSequence($seq_name); + if (DB::isError($result)) { + return $this->raiseError($result); + } + } elseif (!DB::isError($result)) { + $result = $this->query("SELECT IDENT_CURRENT('$seqname')"); + if (DB::isError($result)) { + /* Fallback code for MS SQL Server 7.0, which doesn't have + * IDENT_CURRENT. This is *not* safe for concurrent + * requests, and really, if you're using it, you're in a + * world of hurt. Nevertheless, it's here to ensure BC. See + * bug #181 for the gory details.*/ + $result = $this->query("SELECT @@IDENTITY FROM $seqname"); + } + $repeat = 0; + } else { + $repeat = false; + } + } while ($repeat); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $result = $result->fetchRow(DB_FETCHMODE_ORDERED); + return $result[0]; + } + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_mssql::nextID(), DB_mssql::dropSequence() + */ + function createSequence($seq_name) + { + return $this->query('CREATE TABLE ' + . $this->getSequenceName($seq_name) + . ' ([id] [int] IDENTITY (1, 1) NOT NULL,' + . ' [vapor] [int] NULL)'); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_mssql::nextID(), DB_mssql::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ quoteIdentifier() + + /** + * Quotes a string so it can be safely used as a table or column name + * + * @param string $str identifier name to be quoted + * + * @return string quoted identifier string + * + * @see DB_common::quoteIdentifier() + * @since Method available since Release 1.6.0 + */ + function quoteIdentifier($str) + { + return '[' . str_replace(']', ']]', $str) . ']'; + } + + // }}} + // {{{ mssqlRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_mssql::errorNative(), DB_mssql::errorCode() + */ + function mssqlRaiseError($code = null) + { + $message = @mssql_get_last_message(); + if (!$code) { + $code = $this->errorNative(); + } + return $this->raiseError($this->errorCode($code, $message), + null, null, null, "$code - $message"); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code produced by the last query + * + * @return int the DBMS' error code + */ + function errorNative() + { + $res = @mssql_query('select @@ERROR as ErrorCode', $this->connection); + if (!$res) { + return DB_ERROR; + } + $row = @mssql_fetch_row($res); + return $row[0]; + } + + // }}} + // {{{ errorCode() + + /** + * Determines PEAR::DB error code from mssql's native codes. + * + * If $nativecode isn't known yet, it will be looked up. + * + * @param mixed $nativecode mssql error code, if known + * @return integer an error number from a DB error constant + * @see errorNative() + */ + function errorCode($nativecode = null, $msg = '') + { + if (!$nativecode) { + $nativecode = $this->errorNative(); + } + if (isset($this->errorcode_map[$nativecode])) { + if ($nativecode == 3701 + && preg_match('/Cannot drop the index/i', $msg)) + { + return DB_ERROR_NOT_FOUND; + } + return $this->errorcode_map[$nativecode]; + } else { + return DB_ERROR; + } + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + if (!@mssql_select_db($this->_db, $this->connection)) { + return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED); + } + $id = @mssql_query("SELECT * FROM $result WHERE 1=0", + $this->connection); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->mssqlRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @mssql_num_fields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + if ($got_string) { + $flags = $this->_mssql_field_flags($result, + @mssql_field_name($id, $i)); + if (DB::isError($flags)) { + return $flags; + } + } else { + $flags = ''; + } + + $res[$i] = array( + 'table' => $got_string ? $case_func($result) : '', + 'name' => $case_func(@mssql_field_name($id, $i)), + 'type' => @mssql_field_type($id, $i), + 'len' => @mssql_field_length($id, $i), + 'flags' => $flags, + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @mssql_free_result($id); + } + return $res; + } + + // }}} + // {{{ _mssql_field_flags() + + /** + * Get a column's flags + * + * Supports "not_null", "primary_key", + * "auto_increment" (mssql identity), "timestamp" (mssql timestamp), + * "unique_key" (mssql unique index, unique check or primary_key) and + * "multiple_key" (multikey index) + * + * mssql timestamp is NOT similar to the mysql timestamp so this is maybe + * not useful at all - is the behaviour of mysql_field_flags that primary + * keys are alway unique? is the interpretation of multiple_key correct? + * + * @param string $table the table name + * @param string $column the field name + * + * @return string the flags + * + * @access private + * @author Joern Barthel + */ + function _mssql_field_flags($table, $column) + { + static $tableName = null; + static $flags = array(); + + if ($table != $tableName) { + + $flags = array(); + $tableName = $table; + + // get unique and primary keys + $res = $this->getAll("EXEC SP_HELPINDEX $table", DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + return $res; + } + + foreach ($res as $val) { + $keys = explode(', ', $val['index_keys']); + + if (sizeof($keys) > 1) { + foreach ($keys as $key) { + $this->_add_flag($flags[$key], 'multiple_key'); + } + } + + if (strpos($val['index_description'], 'primary key')) { + foreach ($keys as $key) { + $this->_add_flag($flags[$key], 'primary_key'); + } + } elseif (strpos($val['index_description'], 'unique')) { + foreach ($keys as $key) { + $this->_add_flag($flags[$key], 'unique_key'); + } + } + } + + // get auto_increment, not_null and timestamp + $res = $this->getAll("EXEC SP_COLUMNS $table", DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + return $res; + } + + foreach ($res as $val) { + $val = array_change_key_case($val, CASE_LOWER); + if ($val['nullable'] == '0') { + $this->_add_flag($flags[$val['column_name']], 'not_null'); + } + if (strpos($val['type_name'], 'identity')) { + $this->_add_flag($flags[$val['column_name']], 'auto_increment'); + } + if (strpos($val['type_name'], 'timestamp')) { + $this->_add_flag($flags[$val['column_name']], 'timestamp'); + } + } + } + + if (array_key_exists($column, $flags)) { + return(implode(' ', $flags[$column])); + } + return ''; + } + + // }}} + // {{{ _add_flag() + + /** + * Adds a string to the flags array if the flag is not yet in there + * - if there is no flag present the array is created + * + * @param array &$array the reference to the flag-array + * @param string $value the flag value + * + * @return void + * + * @access private + * @author Joern Barthel + */ + function _add_flag(&$array, $value) + { + if (!is_array($array)) { + $array = array($value); + } elseif (!in_array($value, $array)) { + array_push($array, $value); + } + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return "SELECT name FROM sysobjects WHERE type = 'U'" + . ' ORDER BY name'; + case 'views': + return "SELECT name FROM sysobjects WHERE type = 'V'"; + default: + return null; + } + } + + // }}} +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/mysql.php b/common/PEAR/DB/mysql.php new file mode 100644 index 0000000..103b462 --- /dev/null +++ b/common/PEAR/DB/mysql.php @@ -0,0 +1,1046 @@ + + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: mysql.php,v 1.126 2007/09/21 13:32:52 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's mysql extension + * for interacting with MySQL databases + * + * These methods overload the ones declared in DB_common. + * + * @category Database + * @package DB + * @author Stig Bakken + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_mysql extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'mysql'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'mysql'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'alter', + 'new_link' => '4.2.0', + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => false, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + 1004 => DB_ERROR_CANNOT_CREATE, + 1005 => DB_ERROR_CANNOT_CREATE, + 1006 => DB_ERROR_CANNOT_CREATE, + 1007 => DB_ERROR_ALREADY_EXISTS, + 1008 => DB_ERROR_CANNOT_DROP, + 1022 => DB_ERROR_ALREADY_EXISTS, + 1044 => DB_ERROR_ACCESS_VIOLATION, + 1046 => DB_ERROR_NODBSELECTED, + 1048 => DB_ERROR_CONSTRAINT, + 1049 => DB_ERROR_NOSUCHDB, + 1050 => DB_ERROR_ALREADY_EXISTS, + 1051 => DB_ERROR_NOSUCHTABLE, + 1054 => DB_ERROR_NOSUCHFIELD, + 1061 => DB_ERROR_ALREADY_EXISTS, + 1062 => DB_ERROR_ALREADY_EXISTS, + 1064 => DB_ERROR_SYNTAX, + 1091 => DB_ERROR_NOT_FOUND, + 1100 => DB_ERROR_NOT_LOCKED, + 1136 => DB_ERROR_VALUE_COUNT_ON_ROW, + 1142 => DB_ERROR_ACCESS_VIOLATION, + 1146 => DB_ERROR_NOSUCHTABLE, + 1216 => DB_ERROR_CONSTRAINT, + 1217 => DB_ERROR_CONSTRAINT, + 1356 => DB_ERROR_DIVZERO, + 1451 => DB_ERROR_CONSTRAINT, + 1452 => DB_ERROR_CONSTRAINT, + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * The quantity of transactions begun + * + * {@internal While this is private, it can't actually be designated + * private in PHP 5 because it is directly accessed in the test suite.}} + * + * @var integer + * @access private + */ + var $transaction_opcount = 0; + + /** + * The database specified in the DSN + * + * It's a fix to allow calls to different databases in the same script. + * + * @var string + * @access private + */ + var $_db = ''; + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_mysql() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's mysql driver supports the following extra DSN options: + * + new_link If set to true, causes subsequent calls to connect() + * to return a new connection link instead of the + * existing one. WARNING: this is not portable to + * other DBMS's. Available since PEAR DB 1.7.0. + * + client_flags Any combination of MYSQL_CLIENT_* constants. + * Only used if PHP is at version 4.3.0 or greater. + * Available since PEAR DB 1.7.0. + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('mysql')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $params = array(); + if ($dsn['protocol'] && $dsn['protocol'] == 'unix') { + $params[0] = ':' . $dsn['socket']; + } else { + $params[0] = $dsn['hostspec'] ? $dsn['hostspec'] + : 'localhost'; + if ($dsn['port']) { + $params[0] .= ':' . $dsn['port']; + } + } + $params[] = $dsn['username'] ? $dsn['username'] : null; + $params[] = $dsn['password'] ? $dsn['password'] : null; + + if (!$persistent) { + if (isset($dsn['new_link']) + && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) + { + $params[] = true; + } else { + $params[] = false; + } + } + if (version_compare(phpversion(), '4.3.0', '>=')) { + $params[] = isset($dsn['client_flags']) + ? $dsn['client_flags'] : null; + } + + $connect_function = $persistent ? 'mysql_pconnect' : 'mysql_connect'; + + $ini = ini_get('track_errors'); + $php_errormsg = ''; + if ($ini) { + $this->connection = @call_user_func_array($connect_function, + $params); + } else { + @ini_set('track_errors', 1); + $this->connection = @call_user_func_array($connect_function, + $params); + @ini_set('track_errors', $ini); + } + + if (!$this->connection) { + if (($err = @mysql_error()) != '') { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $err); + } else { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $php_errormsg); + } + } + + if ($dsn['database']) { + if (!@mysql_select_db($dsn['database'], $this->connection)) { + return $this->mysqlRaiseError(); + } + $this->_db = $dsn['database']; + } + + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @mysql_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * Generally uses mysql_query(). If you want to use + * mysql_unbuffered_query() set the "result_buffering" option to 0 using + * setOptions(). This option was added in Release 1.7.0. + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = $this->_checkManip($query); + $this->last_query = $query; + $query = $this->modifyQuery($query); + if ($this->_db) { + if (!@mysql_select_db($this->_db, $this->connection)) { + return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); + } + } + if (!$this->autocommit && $ismanip) { + if ($this->transaction_opcount == 0) { + $result = @mysql_query('SET AUTOCOMMIT=0', $this->connection); + $result = @mysql_query('BEGIN', $this->connection); + if (!$result) { + return $this->mysqlRaiseError(); + } + } + $this->transaction_opcount++; + } + if (!$this->options['result_buffering']) { + $result = @mysql_unbuffered_query($query, $this->connection); + } else { + $result = @mysql_query($query, $this->connection); + } + if (!$result) { + return $this->mysqlRaiseError(); + } + if (is_resource($result)) { + return $result; + } + return DB_OK; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal mysql result pointer to the next available result + * + * This method has not been implemented yet. + * + * @param a valid sql result resource + * + * @return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + if (!@mysql_data_seek($result, $rownum)) { + return null; + } + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @mysql_fetch_array($result, MYSQL_ASSOC); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @mysql_fetch_row($result); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + /* + * Even though this DBMS already trims output, we do this because + * a field might have intentional whitespace at the end that + * gets removed by DB_PORTABILITY_RTRIM under another driver. + */ + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? mysql_free_result($result) : false; + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @mysql_num_fields($result); + if (!$cols) { + return $this->mysqlRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @mysql_num_rows($result); + if ($rows === null) { + return $this->mysqlRaiseError(); + } + return $rows; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + // XXX if $this->transaction_opcount > 0, we should probably + // issue a warning here. + $this->autocommit = $onoff ? true : false; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + if ($this->transaction_opcount > 0) { + if ($this->_db) { + if (!@mysql_select_db($this->_db, $this->connection)) { + return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); + } + } + $result = @mysql_query('COMMIT', $this->connection); + $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->mysqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + if ($this->transaction_opcount > 0) { + if ($this->_db) { + if (!@mysql_select_db($this->_db, $this->connection)) { + return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); + } + } + $result = @mysql_query('ROLLBACK', $this->connection); + $result = @mysql_query('SET AUTOCOMMIT=1', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->mysqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if ($this->_last_query_manip) { + return @mysql_affected_rows($this->connection); + } else { + return 0; + } + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_mysql::createSequence(), DB_mysql::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + do { + $repeat = 0; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("UPDATE ${seqname} ". + 'SET id=LAST_INSERT_ID(id+1)'); + $this->popErrorHandling(); + if ($result === DB_OK) { + // COMMON CASE + $id = @mysql_insert_id($this->connection); + if ($id != 0) { + return $id; + } + // EMPTY SEQ TABLE + // Sequence table must be empty for some reason, so fill + // it and return 1 and obtain a user-level lock + $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); + if (DB::isError($result)) { + return $this->raiseError($result); + } + if ($result == 0) { + // Failed to get the lock + return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); + } + + // add the default value + $result = $this->query("REPLACE INTO ${seqname} (id) VALUES (0)"); + if (DB::isError($result)) { + return $this->raiseError($result); + } + + // Release the lock + $result = $this->getOne('SELECT RELEASE_LOCK(' + . "'${seqname}_lock')"); + if (DB::isError($result)) { + return $this->raiseError($result); + } + // We know what the result will be, so no need to try again + return 1; + + } elseif ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) + { + // ONDEMAND TABLE CREATION + $result = $this->createSequence($seq_name); + if (DB::isError($result)) { + return $this->raiseError($result); + } else { + $repeat = 1; + } + + } elseif (DB::isError($result) && + $result->getCode() == DB_ERROR_ALREADY_EXISTS) + { + // BACKWARDS COMPAT + // see _BCsequence() comment + $result = $this->_BCsequence($seqname); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $repeat = 1; + } + } while ($repeat); + + return $this->raiseError($result); + } + + // }}} + // {{{ createSequence() + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_mysql::nextID(), DB_mysql::dropSequence() + */ + function createSequence($seq_name) + { + $seqname = $this->getSequenceName($seq_name); + $res = $this->query('CREATE TABLE ' . $seqname + . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,' + . ' PRIMARY KEY(id))'); + if (DB::isError($res)) { + return $res; + } + // insert yields value 1, nextId call will generate ID 2 + $res = $this->query("INSERT INTO ${seqname} (id) VALUES (0)"); + if (DB::isError($res)) { + return $res; + } + // so reset to zero + return $this->query("UPDATE ${seqname} SET id = 0"); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_mysql::nextID(), DB_mysql::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ _BCsequence() + + /** + * Backwards compatibility with old sequence emulation implementation + * (clean up the dupes) + * + * @param string $seqname the sequence name to clean up + * + * @return bool true on success. A DB_Error object on failure. + * + * @access private + */ + function _BCsequence($seqname) + { + // Obtain a user-level lock... this will release any previous + // application locks, but unlike LOCK TABLES, it does not abort + // the current transaction and is much less frequently used. + $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); + if (DB::isError($result)) { + return $result; + } + if ($result == 0) { + // Failed to get the lock, can't do the conversion, bail + // with a DB_ERROR_NOT_LOCKED error + return $this->mysqlRaiseError(DB_ERROR_NOT_LOCKED); + } + + $highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}"); + if (DB::isError($highest_id)) { + return $highest_id; + } + // This should kill all rows except the highest + // We should probably do something if $highest_id isn't + // numeric, but I'm at a loss as how to handle that... + $result = $this->query('DELETE FROM ' . $seqname + . " WHERE id <> $highest_id"); + if (DB::isError($result)) { + return $result; + } + + // If another thread has been waiting for this lock, + // it will go thru the above procedure, but will have no + // real effect + $result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')"); + if (DB::isError($result)) { + return $result; + } + return true; + } + + // }}} + // {{{ quoteIdentifier() + + /** + * Quotes a string so it can be safely used as a table or column name + * (WARNING: using names that require this is a REALLY BAD IDEA) + * + * WARNING: Older versions of MySQL can't handle the backtick + * character (`) in table or column names. + * + * @param string $str identifier name to be quoted + * + * @return string quoted identifier string + * + * @see DB_common::quoteIdentifier() + * @since Method available since Release 1.6.0 + */ + function quoteIdentifier($str) + { + return '`' . str_replace('`', '``', $str) . '`'; + } + + // }}} + // {{{ quote() + + /** + * @deprecated Deprecated in release 1.6.0 + */ + function quote($str) + { + return $this->quoteSmart($str); + } + + // }}} + // {{{ escapeSimple() + + /** + * Escapes a string according to the current DBMS's standards + * + * @param string $str the string to be escaped + * + * @return string the escaped string + * + * @see DB_common::quoteSmart() + * @since Method available since Release 1.6.0 + */ + function escapeSimple($str) + { + if (function_exists('mysql_real_escape_string')) { + return @mysql_real_escape_string($str, $this->connection); + } else { + return @mysql_escape_string($str); + } + } + + + // }}} + // {{{ modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * This little hack lets you know how many rows were deleted + * when running a "DELETE FROM table" query. Only implemented + * if the DB_PORTABILITY_DELETE_COUNT portability option is on. + * + * @param string $query the query string to modify + * + * @return string the modified query string + * + * @access protected + * @see DB_common::setOption() + */ + function modifyQuery($query) + { + if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) { + // "DELETE FROM table" gives 0 affected rows in MySQL. + // This little hack lets you know how many rows were deleted. + if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) { + $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/', + 'DELETE FROM \1 WHERE 1=1', $query); + } + } + return $query; + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + if (DB::isManip($query) || $this->_next_query_manip) { + return $query . " LIMIT $count"; + } else { + return $query . " LIMIT $from, $count"; + } + } + + // }}} + // {{{ mysqlRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_mysql::errorNative(), DB_common::errorCode() + */ + function mysqlRaiseError($errno = null) + { + if ($errno === null) { + if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { + $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT; + $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL; + $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT; + } else { + // Doing this in case mode changes during runtime. + $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS; + $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT; + $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS; + } + $errno = $this->errorCode(mysql_errno($this->connection)); + } + return $this->raiseError($errno, null, null, null, + @mysql_errno($this->connection) . ' ** ' . + @mysql_error($this->connection)); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code produced by the last query + * + * @return int the DBMS' error code + */ + function errorNative() + { + return @mysql_errno($this->connection); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + // Fix for bug #11580. + if ($this->_db) { + if (!@mysql_select_db($this->_db, $this->connection)) { + return $this->mysqlRaiseError(DB_ERROR_NODBSELECTED); + } + } + + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @mysql_query("SELECT * FROM $result LIMIT 0", + $this->connection); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->mysqlRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @mysql_num_fields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => $case_func(@mysql_field_table($id, $i)), + 'name' => $case_func(@mysql_field_name($id, $i)), + 'type' => @mysql_field_type($id, $i), + 'len' => @mysql_field_len($id, $i), + 'flags' => @mysql_field_flags($id, $i), + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @mysql_free_result($id); + } + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return 'SHOW TABLES'; + case 'users': + return 'SELECT DISTINCT User FROM mysql.user'; + case 'databases': + return 'SHOW DATABASES'; + default: + return null; + } + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/mysqli.php b/common/PEAR/DB/mysqli.php new file mode 100644 index 0000000..e02c18d --- /dev/null +++ b/common/PEAR/DB/mysqli.php @@ -0,0 +1,1092 @@ + + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: mysqli.php,v 1.82 2007/09/21 13:40:41 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's mysqli extension + * for interacting with MySQL databases + * + * This is for MySQL versions 4.1 and above. Requires PHP 5. + * + * Note that persistent connections no longer exist. + * + * These methods overload the ones declared in DB_common. + * + * @category Database + * @package DB + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + * @since Class functional since Release 1.6.3 + */ +class DB_mysqli extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'mysqli'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'mysqli'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'alter', + 'new_link' => false, + 'numrows' => true, + 'pconnect' => false, + 'prepare' => false, + 'ssl' => true, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + 1004 => DB_ERROR_CANNOT_CREATE, + 1005 => DB_ERROR_CANNOT_CREATE, + 1006 => DB_ERROR_CANNOT_CREATE, + 1007 => DB_ERROR_ALREADY_EXISTS, + 1008 => DB_ERROR_CANNOT_DROP, + 1022 => DB_ERROR_ALREADY_EXISTS, + 1044 => DB_ERROR_ACCESS_VIOLATION, + 1046 => DB_ERROR_NODBSELECTED, + 1048 => DB_ERROR_CONSTRAINT, + 1049 => DB_ERROR_NOSUCHDB, + 1050 => DB_ERROR_ALREADY_EXISTS, + 1051 => DB_ERROR_NOSUCHTABLE, + 1054 => DB_ERROR_NOSUCHFIELD, + 1061 => DB_ERROR_ALREADY_EXISTS, + 1062 => DB_ERROR_ALREADY_EXISTS, + 1064 => DB_ERROR_SYNTAX, + 1091 => DB_ERROR_NOT_FOUND, + 1100 => DB_ERROR_NOT_LOCKED, + 1136 => DB_ERROR_VALUE_COUNT_ON_ROW, + 1142 => DB_ERROR_ACCESS_VIOLATION, + 1146 => DB_ERROR_NOSUCHTABLE, + 1216 => DB_ERROR_CONSTRAINT, + 1217 => DB_ERROR_CONSTRAINT, + 1356 => DB_ERROR_DIVZERO, + 1451 => DB_ERROR_CONSTRAINT, + 1452 => DB_ERROR_CONSTRAINT, + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * The quantity of transactions begun + * + * {@internal While this is private, it can't actually be designated + * private in PHP 5 because it is directly accessed in the test suite.}} + * + * @var integer + * @access private + */ + var $transaction_opcount = 0; + + /** + * The database specified in the DSN + * + * It's a fix to allow calls to different databases in the same script. + * + * @var string + * @access private + */ + var $_db = ''; + + /** + * Array for converting MYSQLI_*_FLAG constants to text values + * @var array + * @access public + * @since Property available since Release 1.6.5 + */ + var $mysqli_flags = array( + MYSQLI_NOT_NULL_FLAG => 'not_null', + MYSQLI_PRI_KEY_FLAG => 'primary_key', + MYSQLI_UNIQUE_KEY_FLAG => 'unique_key', + MYSQLI_MULTIPLE_KEY_FLAG => 'multiple_key', + MYSQLI_BLOB_FLAG => 'blob', + MYSQLI_UNSIGNED_FLAG => 'unsigned', + MYSQLI_ZEROFILL_FLAG => 'zerofill', + MYSQLI_AUTO_INCREMENT_FLAG => 'auto_increment', + MYSQLI_TIMESTAMP_FLAG => 'timestamp', + MYSQLI_SET_FLAG => 'set', + // MYSQLI_NUM_FLAG => 'numeric', // unnecessary + // MYSQLI_PART_KEY_FLAG => 'multiple_key', // duplicatvie + MYSQLI_GROUP_FLAG => 'group_by' + ); + + /** + * Array for converting MYSQLI_TYPE_* constants to text values + * @var array + * @access public + * @since Property available since Release 1.6.5 + */ + var $mysqli_types = array( + MYSQLI_TYPE_DECIMAL => 'decimal', + MYSQLI_TYPE_TINY => 'tinyint', + MYSQLI_TYPE_SHORT => 'int', + MYSQLI_TYPE_LONG => 'int', + MYSQLI_TYPE_FLOAT => 'float', + MYSQLI_TYPE_DOUBLE => 'double', + // MYSQLI_TYPE_NULL => 'DEFAULT NULL', // let flags handle it + MYSQLI_TYPE_TIMESTAMP => 'timestamp', + MYSQLI_TYPE_LONGLONG => 'bigint', + MYSQLI_TYPE_INT24 => 'mediumint', + MYSQLI_TYPE_DATE => 'date', + MYSQLI_TYPE_TIME => 'time', + MYSQLI_TYPE_DATETIME => 'datetime', + MYSQLI_TYPE_YEAR => 'year', + MYSQLI_TYPE_NEWDATE => 'date', + MYSQLI_TYPE_ENUM => 'enum', + MYSQLI_TYPE_SET => 'set', + MYSQLI_TYPE_TINY_BLOB => 'tinyblob', + MYSQLI_TYPE_MEDIUM_BLOB => 'mediumblob', + MYSQLI_TYPE_LONG_BLOB => 'longblob', + MYSQLI_TYPE_BLOB => 'blob', + MYSQLI_TYPE_VAR_STRING => 'varchar', + MYSQLI_TYPE_STRING => 'char', + MYSQLI_TYPE_GEOMETRY => 'geometry', + /* These constants are conditionally compiled in ext/mysqli, so we'll + * define them by number rather than constant. */ + 16 => 'bit', + 246 => 'decimal', + ); + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_mysqli() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's mysqli driver supports the following extra DSN options: + * + When the 'ssl' $option passed to DB::connect() is true: + * + key The path to the key file. + * + cert The path to the certificate file. + * + ca The path to the certificate authority file. + * + capath The path to a directory that contains trusted SSL + * CA certificates in pem format. + * + cipher The list of allowable ciphers for SSL encryption. + * + * Example of how to connect using SSL: + * + * require_once 'DB.php'; + * + * $dsn = array( + * 'phptype' => 'mysqli', + * 'username' => 'someuser', + * 'password' => 'apasswd', + * 'hostspec' => 'localhost', + * 'database' => 'thedb', + * 'key' => 'client-key.pem', + * 'cert' => 'client-cert.pem', + * 'ca' => 'cacert.pem', + * 'capath' => '/path/to/ca/dir', + * 'cipher' => 'AES', + * ); + * + * $options = array( + * 'ssl' => true, + * ); + * + * $db = DB::connect($dsn, $options); + * if (PEAR::isError($db)) { + * die($db->getMessage()); + * } + * + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('mysqli')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $ini = ini_get('track_errors'); + @ini_set('track_errors', 1); + $php_errormsg = ''; + + if (((int) $this->getOption('ssl')) === 1) { + $init = mysqli_init(); + mysqli_ssl_set( + $init, + empty($dsn['key']) ? null : $dsn['key'], + empty($dsn['cert']) ? null : $dsn['cert'], + empty($dsn['ca']) ? null : $dsn['ca'], + empty($dsn['capath']) ? null : $dsn['capath'], + empty($dsn['cipher']) ? null : $dsn['cipher'] + ); + if ($this->connection = @mysqli_real_connect( + $init, + $dsn['hostspec'], + $dsn['username'], + $dsn['password'], + $dsn['database'], + $dsn['port'], + $dsn['socket'])) + { + $this->connection = $init; + } + } else { + $this->connection = @mysqli_connect( + $dsn['hostspec'], + $dsn['username'], + $dsn['password'], + $dsn['database'], + $dsn['port'], + $dsn['socket'] + ); + } + + @ini_set('track_errors', $ini); + + if (!$this->connection) { + if (($err = @mysqli_connect_error()) != '') { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $err); + } else { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $php_errormsg); + } + } + + if ($dsn['database']) { + $this->_db = $dsn['database']; + } + + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @mysqli_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = $this->_checkManip($query); + $this->last_query = $query; + $query = $this->modifyQuery($query); + if ($this->_db) { + if (!@mysqli_select_db($this->connection, $this->_db)) { + return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); + } + } + if (!$this->autocommit && $ismanip) { + if ($this->transaction_opcount == 0) { + $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=0'); + $result = @mysqli_query($this->connection, 'BEGIN'); + if (!$result) { + return $this->mysqliRaiseError(); + } + } + $this->transaction_opcount++; + } + $result = @mysqli_query($this->connection, $query); + if (!$result) { + return $this->mysqliRaiseError(); + } + if (is_object($result)) { + return $result; + } + return DB_OK; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal mysql result pointer to the next available result. + * + * This method has not been implemented yet. + * + * @param resource $result a valid sql result resource + * @return false + * @access public + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + if (!@mysqli_data_seek($result, $rownum)) { + return null; + } + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @mysqli_fetch_array($result, MYSQLI_ASSOC); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @mysqli_fetch_row($result); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + /* + * Even though this DBMS already trims output, we do this because + * a field might have intentional whitespace at the end that + * gets removed by DB_PORTABILITY_RTRIM under another driver. + */ + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? mysqli_free_result($result) : false; + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @mysqli_num_fields($result); + if (!$cols) { + return $this->mysqliRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @mysqli_num_rows($result); + if ($rows === null) { + return $this->mysqliRaiseError(); + } + return $rows; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + // XXX if $this->transaction_opcount > 0, we should probably + // issue a warning here. + $this->autocommit = $onoff ? true : false; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + if ($this->transaction_opcount > 0) { + if ($this->_db) { + if (!@mysqli_select_db($this->connection, $this->_db)) { + return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); + } + } + $result = @mysqli_query($this->connection, 'COMMIT'); + $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1'); + $this->transaction_opcount = 0; + if (!$result) { + return $this->mysqliRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + if ($this->transaction_opcount > 0) { + if ($this->_db) { + if (!@mysqli_select_db($this->connection, $this->_db)) { + return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); + } + } + $result = @mysqli_query($this->connection, 'ROLLBACK'); + $result = @mysqli_query($this->connection, 'SET AUTOCOMMIT=1'); + $this->transaction_opcount = 0; + if (!$result) { + return $this->mysqliRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if ($this->_last_query_manip) { + return @mysqli_affected_rows($this->connection); + } else { + return 0; + } + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_mysqli::createSequence(), DB_mysqli::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + do { + $repeat = 0; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query('UPDATE ' . $seqname + . ' SET id = LAST_INSERT_ID(id + 1)'); + $this->popErrorHandling(); + if ($result === DB_OK) { + // COMMON CASE + $id = @mysqli_insert_id($this->connection); + if ($id != 0) { + return $id; + } + + // EMPTY SEQ TABLE + // Sequence table must be empty for some reason, + // so fill it and return 1 + // Obtain a user-level lock + $result = $this->getOne('SELECT GET_LOCK(' + . "'${seqname}_lock', 10)"); + if (DB::isError($result)) { + return $this->raiseError($result); + } + if ($result == 0) { + return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED); + } + + // add the default value + $result = $this->query('REPLACE INTO ' . $seqname + . ' (id) VALUES (0)'); + if (DB::isError($result)) { + return $this->raiseError($result); + } + + // Release the lock + $result = $this->getOne('SELECT RELEASE_LOCK(' + . "'${seqname}_lock')"); + if (DB::isError($result)) { + return $this->raiseError($result); + } + // We know what the result will be, so no need to try again + return 1; + + } elseif ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) + { + // ONDEMAND TABLE CREATION + $result = $this->createSequence($seq_name); + + // Since createSequence initializes the ID to be 1, + // we do not need to retrieve the ID again (or we will get 2) + if (DB::isError($result)) { + return $this->raiseError($result); + } else { + // First ID of a newly created sequence is 1 + return 1; + } + + } elseif (DB::isError($result) && + $result->getCode() == DB_ERROR_ALREADY_EXISTS) + { + // BACKWARDS COMPAT + // see _BCsequence() comment + $result = $this->_BCsequence($seqname); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $repeat = 1; + } + } while ($repeat); + + return $this->raiseError($result); + } + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_mysqli::nextID(), DB_mysqli::dropSequence() + */ + function createSequence($seq_name) + { + $seqname = $this->getSequenceName($seq_name); + $res = $this->query('CREATE TABLE ' . $seqname + . ' (id INTEGER UNSIGNED AUTO_INCREMENT NOT NULL,' + . ' PRIMARY KEY(id))'); + if (DB::isError($res)) { + return $res; + } + // insert yields value 1, nextId call will generate ID 2 + return $this->query("INSERT INTO ${seqname} (id) VALUES (0)"); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_mysql::nextID(), DB_mysql::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ _BCsequence() + + /** + * Backwards compatibility with old sequence emulation implementation + * (clean up the dupes) + * + * @param string $seqname the sequence name to clean up + * + * @return bool true on success. A DB_Error object on failure. + * + * @access private + */ + function _BCsequence($seqname) + { + // Obtain a user-level lock... this will release any previous + // application locks, but unlike LOCK TABLES, it does not abort + // the current transaction and is much less frequently used. + $result = $this->getOne("SELECT GET_LOCK('${seqname}_lock',10)"); + if (DB::isError($result)) { + return $result; + } + if ($result == 0) { + // Failed to get the lock, can't do the conversion, bail + // with a DB_ERROR_NOT_LOCKED error + return $this->mysqliRaiseError(DB_ERROR_NOT_LOCKED); + } + + $highest_id = $this->getOne("SELECT MAX(id) FROM ${seqname}"); + if (DB::isError($highest_id)) { + return $highest_id; + } + + // This should kill all rows except the highest + // We should probably do something if $highest_id isn't + // numeric, but I'm at a loss as how to handle that... + $result = $this->query('DELETE FROM ' . $seqname + . " WHERE id <> $highest_id"); + if (DB::isError($result)) { + return $result; + } + + // If another thread has been waiting for this lock, + // it will go thru the above procedure, but will have no + // real effect + $result = $this->getOne("SELECT RELEASE_LOCK('${seqname}_lock')"); + if (DB::isError($result)) { + return $result; + } + return true; + } + + // }}} + // {{{ quoteIdentifier() + + /** + * Quotes a string so it can be safely used as a table or column name + * (WARNING: using names that require this is a REALLY BAD IDEA) + * + * WARNING: Older versions of MySQL can't handle the backtick + * character (`) in table or column names. + * + * @param string $str identifier name to be quoted + * + * @return string quoted identifier string + * + * @see DB_common::quoteIdentifier() + * @since Method available since Release 1.6.0 + */ + function quoteIdentifier($str) + { + return '`' . str_replace('`', '``', $str) . '`'; + } + + // }}} + // {{{ escapeSimple() + + /** + * Escapes a string according to the current DBMS's standards + * + * @param string $str the string to be escaped + * + * @return string the escaped string + * + * @see DB_common::quoteSmart() + * @since Method available since Release 1.6.0 + */ + function escapeSimple($str) + { + return @mysqli_real_escape_string($this->connection, $str); + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + if (DB::isManip($query) || $this->_next_query_manip) { + return $query . " LIMIT $count"; + } else { + return $query . " LIMIT $from, $count"; + } + } + + // }}} + // {{{ mysqliRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_mysqli::errorNative(), DB_common::errorCode() + */ + function mysqliRaiseError($errno = null) + { + if ($errno === null) { + if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { + $this->errorcode_map[1022] = DB_ERROR_CONSTRAINT; + $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT_NOT_NULL; + $this->errorcode_map[1062] = DB_ERROR_CONSTRAINT; + } else { + // Doing this in case mode changes during runtime. + $this->errorcode_map[1022] = DB_ERROR_ALREADY_EXISTS; + $this->errorcode_map[1048] = DB_ERROR_CONSTRAINT; + $this->errorcode_map[1062] = DB_ERROR_ALREADY_EXISTS; + } + $errno = $this->errorCode(mysqli_errno($this->connection)); + } + return $this->raiseError($errno, null, null, null, + @mysqli_errno($this->connection) . ' ** ' . + @mysqli_error($this->connection)); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code produced by the last query + * + * @return int the DBMS' error code + */ + function errorNative() + { + return @mysqli_errno($this->connection); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::setOption() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + // Fix for bug #11580. + if ($this->_db) { + if (!@mysqli_select_db($this->connection, $this->_db)) { + return $this->mysqliRaiseError(DB_ERROR_NODBSELECTED); + } + } + + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @mysqli_query($this->connection, + "SELECT * FROM $result LIMIT 0"); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_a($id, 'mysqli_result')) { + return $this->mysqliRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @mysqli_num_fields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $tmp = @mysqli_fetch_field($id); + + $flags = ''; + foreach ($this->mysqli_flags as $const => $means) { + if ($tmp->flags & $const) { + $flags .= $means . ' '; + } + } + if ($tmp->def) { + $flags .= 'default_' . rawurlencode($tmp->def); + } + $flags = trim($flags); + + $res[$i] = array( + 'table' => $case_func($tmp->table), + 'name' => $case_func($tmp->name), + 'type' => isset($this->mysqli_types[$tmp->type]) + ? $this->mysqli_types[$tmp->type] + : 'unknown', + // http://bugs.php.net/?id=36579 + 'len' => $tmp->length, + 'flags' => $flags, + ); + + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @mysqli_free_result($id); + } + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return 'SHOW TABLES'; + case 'users': + return 'SELECT DISTINCT User FROM mysql.user'; + case 'databases': + return 'SHOW DATABASES'; + default: + return null; + } + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/oci8.php b/common/PEAR/DB/oci8.php new file mode 100644 index 0000000..fcdc21c --- /dev/null +++ b/common/PEAR/DB/oci8.php @@ -0,0 +1,1156 @@ + + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: oci8.php,v 1.115 2007/09/21 13:40:41 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's oci8 extension + * for interacting with Oracle databases + * + * Definitely works with versions 8 and 9 of Oracle. + * + * These methods overload the ones declared in DB_common. + * + * Be aware... OCIError() only appears to return anything when given a + * statement, so functions return the generic DB_ERROR instead of more + * useful errors that have to do with feedback from the database. + * + * @category Database + * @package DB + * @author James L. Pine + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_oci8 extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'oci8'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'oci8'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'alter', + 'new_link' => '5.0.0', + 'numrows' => 'subquery', + 'pconnect' => true, + 'prepare' => true, + 'ssl' => false, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + 1 => DB_ERROR_CONSTRAINT, + 900 => DB_ERROR_SYNTAX, + 904 => DB_ERROR_NOSUCHFIELD, + 913 => DB_ERROR_VALUE_COUNT_ON_ROW, + 921 => DB_ERROR_SYNTAX, + 923 => DB_ERROR_SYNTAX, + 942 => DB_ERROR_NOSUCHTABLE, + 955 => DB_ERROR_ALREADY_EXISTS, + 1400 => DB_ERROR_CONSTRAINT_NOT_NULL, + 1401 => DB_ERROR_INVALID, + 1407 => DB_ERROR_CONSTRAINT_NOT_NULL, + 1418 => DB_ERROR_NOT_FOUND, + 1476 => DB_ERROR_DIVZERO, + 1722 => DB_ERROR_INVALID_NUMBER, + 2289 => DB_ERROR_NOSUCHTABLE, + 2291 => DB_ERROR_CONSTRAINT, + 2292 => DB_ERROR_CONSTRAINT, + 2449 => DB_ERROR_CONSTRAINT, + 12899 => DB_ERROR_INVALID, + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * Stores the $data passed to execute() in the oci8 driver + * + * Gets reset to array() when simpleQuery() is run. + * + * Needed in case user wants to call numRows() after prepare/execute + * was used. + * + * @var array + * @access private + */ + var $_data = array(); + + /** + * The result or statement handle from the most recently executed query + * @var resource + */ + var $last_stmt; + + /** + * Is the given prepared statement a data manipulation query? + * @var array + * @access private + */ + var $manip_query = array(); + + /** + * Store of prepared SQL queries. + * @var array + * @access private + */ + var $_prepared_queries = array(); + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_oci8() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * If PHP is at version 5.0.0 or greater: + * + Generally, oci_connect() or oci_pconnect() are used. + * + But if the new_link DSN option is set to true, oci_new_connect() + * is used. + * + * When using PHP version 4.x, OCILogon() or OCIPLogon() are used. + * + * PEAR DB's oci8 driver supports the following extra DSN options: + * + charset The character set to be used on the connection. + * Only used if PHP is at version 5.0.0 or greater + * and the Oracle server is at 9.2 or greater. + * Available since PEAR DB 1.7.0. + * + new_link If set to true, causes subsequent calls to + * connect() to return a new connection link + * instead of the existing one. WARNING: this is + * not portable to other DBMS's. + * Available since PEAR DB 1.7.0. + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('oci8')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + // Backwards compatibility with DB < 1.7.0 + if (empty($dsn['database']) && !empty($dsn['hostspec'])) { + $db = $dsn['hostspec']; + } else { + $db = $dsn['database']; + } + + if (function_exists('oci_connect')) { + if (isset($dsn['new_link']) + && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) + { + $connect_function = 'oci_new_connect'; + } else { + $connect_function = $persistent ? 'oci_pconnect' + : 'oci_connect'; + } + if (isset($this->dsn['port']) && $this->dsn['port']) { + $db = '//'.$db.':'.$this->dsn['port']; + } + + $char = empty($dsn['charset']) ? null : $dsn['charset']; + $this->connection = @$connect_function($dsn['username'], + $dsn['password'], + $db, + $char); + $error = OCIError(); + if (!empty($error) && $error['code'] == 12541) { + // Couldn't find TNS listener. Try direct connection. + $this->connection = @$connect_function($dsn['username'], + $dsn['password'], + null, + $char); + } + } else { + $connect_function = $persistent ? 'OCIPLogon' : 'OCILogon'; + if ($db) { + $this->connection = @$connect_function($dsn['username'], + $dsn['password'], + $db); + } elseif ($dsn['username'] || $dsn['password']) { + $this->connection = @$connect_function($dsn['username'], + $dsn['password']); + } + } + + if (!$this->connection) { + $error = OCIError(); + $error = (is_array($error)) ? $error['message'] : null; + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $error); + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + if (function_exists('oci_close')) { + $ret = @oci_close($this->connection); + } else { + $ret = @OCILogOff($this->connection); + } + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * To determine how many rows of a result set get buffered using + * ocisetprefetch(), see the "result_buffering" option in setOptions(). + * This option was added in Release 1.7.0. + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $this->_data = array(); + $this->last_parameters = array(); + $this->last_query = $query; + $query = $this->modifyQuery($query); + $result = @OCIParse($this->connection, $query); + if (!$result) { + return $this->oci8RaiseError(); + } + if ($this->autocommit) { + $success = @OCIExecute($result,OCI_COMMIT_ON_SUCCESS); + } else { + $success = @OCIExecute($result,OCI_DEFAULT); + } + if (!$success) { + return $this->oci8RaiseError($result); + } + $this->last_stmt = $result; + if ($this->_checkManip($query)) { + return DB_OK; + } else { + @ocisetprefetch($result, $this->options['result_buffering']); + return $result; + } + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal oracle result pointer to the next available result + * + * @param a valid oci8 result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $moredata = @OCIFetchInto($result,$arr,OCI_ASSOC+OCI_RETURN_NULLS+OCI_RETURN_LOBS); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && + $moredata) + { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $moredata = OCIFetchInto($result,$arr,OCI_RETURN_NULLS+OCI_RETURN_LOBS); + } + if (!$moredata) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? OCIFreeStatement($result) : false; + } + + /** + * Frees the internal resources associated with a prepared query + * + * @param resource $stmt the prepared statement's resource + * @param bool $free_resource should the PHP resource be freed too? + * Use false if you need to get data + * from the result set later. + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_oci8::prepare() + */ + function freePrepared($stmt, $free_resource = true) + { + if (!is_resource($stmt)) { + return false; + } + if ($free_resource) { + @ocifreestatement($stmt); + } + if (isset($this->prepare_types[(int)$stmt])) { + unset($this->prepare_types[(int)$stmt]); + unset($this->manip_query[(int)$stmt]); + } else { + return false; + } + return true; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * Only works if the DB_PORTABILITY_NUMROWS portability option + * is turned on. + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows(), DB_common::setOption() + */ + function numRows($result) + { + // emulate numRows for Oracle. yuck. + if ($this->options['portability'] & DB_PORTABILITY_NUMROWS && + $result === $this->last_stmt) + { + $countquery = 'SELECT COUNT(*) FROM ('.$this->last_query.')'; + $save_query = $this->last_query; + $save_stmt = $this->last_stmt; + + $count = $this->query($countquery); + + // Restore the last query and statement. + $this->last_query = $save_query; + $this->last_stmt = $save_stmt; + + if (DB::isError($count) || + DB::isError($row = $count->fetchRow(DB_FETCHMODE_ORDERED))) + { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + return $row[0]; + } + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @OCINumCols($result); + if (!$cols) { + return $this->oci8RaiseError($result); + } + return $cols; + } + + // }}} + // {{{ prepare() + + /** + * Prepares a query for multiple execution with execute(). + * + * With oci8, this is emulated. + * + * prepare() requires a generic query as string like + * INSERT INTO numbers VALUES (?, ?, ?) + * . The ? characters are placeholders. + * + * Three types of placeholders can be used: + * + ? a quoted scalar value, i.e. strings, integers + * + ! value is inserted 'as is' + * + & requires a file name. The file's contents get + * inserted into the query (i.e. saving binary + * data in a db) + * + * Use backslashes to escape placeholder characters if you don't want + * them to be interpreted as placeholders. Example: + * "UPDATE foo SET col=? WHERE col='over \& under'" + * + * + * @param string $query the query to be prepared + * + * @return mixed DB statement resource on success. DB_Error on failure. + * + * @see DB_oci8::execute() + */ + function prepare($query) + { + $tokens = preg_split('/((? $val) { + switch ($val) { + case '?': + $types[$token++] = DB_PARAM_SCALAR; + unset($tokens[$key]); + break; + case '&': + $types[$token++] = DB_PARAM_OPAQUE; + unset($tokens[$key]); + break; + case '!': + $types[$token++] = DB_PARAM_MISC; + unset($tokens[$key]); + break; + default: + $tokens[$key] = preg_replace('/\\\([&?!])/', "\\1", $val); + if ($key != $binds) { + $newquery .= $tokens[$key] . ':bind' . $token; + } else { + $newquery .= $tokens[$key]; + } + } + } + + $this->last_query = $query; + $newquery = $this->modifyQuery($newquery); + if (!$stmt = @OCIParse($this->connection, $newquery)) { + return $this->oci8RaiseError(); + } + $this->prepare_types[(int)$stmt] = $types; + $this->manip_query[(int)$stmt] = DB::isManip($query); + $this->_prepared_queries[(int)$stmt] = $newquery; + return $stmt; + } + + // }}} + // {{{ execute() + + /** + * Executes a DB statement prepared with prepare(). + * + * To determine how many rows of a result set get buffered using + * ocisetprefetch(), see the "result_buffering" option in setOptions(). + * This option was added in Release 1.7.0. + * + * @param resource $stmt a DB statement resource returned from prepare() + * @param mixed $data array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 for non-array items or the + * quantity of elements in the array. + * + * @return mixed returns an oic8 result resource for successful SELECT + * queries, DB_OK for other successful queries. + * A DB error object is returned on failure. + * + * @see DB_oci8::prepare() + */ + function &execute($stmt, $data = array()) + { + $data = (array)$data; + $this->last_parameters = $data; + $this->last_query = $this->_prepared_queries[(int)$stmt]; + $this->_data = $data; + + $types = $this->prepare_types[(int)$stmt]; + if (count($types) != count($data)) { + $tmp = $this->raiseError(DB_ERROR_MISMATCH); + return $tmp; + } + + $i = 0; + foreach ($data as $key => $value) { + if ($types[$i] == DB_PARAM_MISC) { + /* + * Oracle doesn't seem to have the ability to pass a + * parameter along unchanged, so strip off quotes from start + * and end, plus turn two single quotes to one single quote, + * in order to avoid the quotes getting escaped by + * Oracle and ending up in the database. + */ + $data[$key] = preg_replace("/^'(.*)'$/", "\\1", $data[$key]); + $data[$key] = str_replace("''", "'", $data[$key]); + } elseif ($types[$i] == DB_PARAM_OPAQUE) { + $fp = @fopen($data[$key], 'rb'); + if (!$fp) { + $tmp = $this->raiseError(DB_ERROR_ACCESS_VIOLATION); + return $tmp; + } + $data[$key] = fread($fp, filesize($data[$key])); + fclose($fp); + } elseif ($types[$i] == DB_PARAM_SCALAR) { + // Floats have to be converted to a locale-neutral + // representation. + if (is_float($data[$key])) { + $data[$key] = $this->quoteFloat($data[$key]); + } + } + if (!@OCIBindByName($stmt, ':bind' . $i, $data[$key], -1)) { + $tmp = $this->oci8RaiseError($stmt); + return $tmp; + } + $this->last_query = str_replace(':bind'.$i, $this->quoteSmart($data[$key]), $this->last_query); + $i++; + } + if ($this->autocommit) { + $success = @OCIExecute($stmt, OCI_COMMIT_ON_SUCCESS); + } else { + $success = @OCIExecute($stmt, OCI_DEFAULT); + } + if (!$success) { + $tmp = $this->oci8RaiseError($stmt); + return $tmp; + } + $this->last_stmt = $stmt; + if ($this->manip_query[(int)$stmt] || $this->_next_query_manip) { + $this->_last_query_manip = true; + $this->_next_query_manip = false; + $tmp = DB_OK; + } else { + $this->_last_query_manip = false; + @ocisetprefetch($stmt, $this->options['result_buffering']); + $tmp = new DB_result($this, $stmt); + } + return $tmp; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + $this->autocommit = (bool)$onoff;; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + $result = @OCICommit($this->connection); + if (!$result) { + return $this->oci8RaiseError(); + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + $result = @OCIRollback($this->connection); + if (!$result) { + return $this->oci8RaiseError(); + } + return DB_OK; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if ($this->last_stmt === false) { + return $this->oci8RaiseError(); + } + $result = @OCIRowCount($this->last_stmt); + if ($result === false) { + return $this->oci8RaiseError($this->last_stmt); + } + return $result; + } + + // }}} + // {{{ modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * "SELECT 2+2" must be "SELECT 2+2 FROM dual" in Oracle. + * + * @param string $query the query string to modify + * + * @return string the modified query string + * + * @access protected + */ + function modifyQuery($query) + { + if (preg_match('/^\s*SELECT/i', $query) && + !preg_match('/\sFROM\s/i', $query)) { + $query .= ' FROM dual'; + } + return $query; + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + // Let Oracle return the name of the columns instead of + // coding a "home" SQL parser + + if (count($params)) { + $result = $this->prepare("SELECT * FROM ($query) " + . 'WHERE NULL = NULL'); + $tmp = $this->execute($result, $params); + } else { + $q_fields = "SELECT * FROM ($query) WHERE NULL = NULL"; + + if (!$result = @OCIParse($this->connection, $q_fields)) { + $this->last_query = $q_fields; + return $this->oci8RaiseError(); + } + if (!@OCIExecute($result, OCI_DEFAULT)) { + $this->last_query = $q_fields; + return $this->oci8RaiseError($result); + } + } + + $ncols = OCINumCols($result); + $cols = array(); + for ( $i = 1; $i <= $ncols; $i++ ) { + $cols[] = '"' . OCIColumnName($result, $i) . '"'; + } + $fields = implode(', ', $cols); + // XXX Test that (tip by John Lim) + //if (preg_match('/^\s*SELECT\s+/is', $query, $match)) { + // // Introduce the FIRST_ROWS Oracle query optimizer + // $query = substr($query, strlen($match[0]), strlen($query)); + // $query = "SELECT /* +FIRST_ROWS */ " . $query; + //} + + // Construct the query + // more at: http://marc.theaimsgroup.com/?l=php-db&m=99831958101212&w=2 + // Perhaps this could be optimized with the use of Unions + $query = "SELECT $fields FROM". + " (SELECT rownum as linenum, $fields FROM". + " ($query)". + ' WHERE rownum <= '. ($from + $count) . + ') WHERE linenum >= ' . ++$from; + return $query; + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_oci8::createSequence(), DB_oci8::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + $repeat = 0; + do { + $this->expectError(DB_ERROR_NOSUCHTABLE); + $result = $this->query("SELECT ${seqname}.nextval FROM dual"); + $this->popExpect(); + if ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) { + $repeat = 1; + $result = $this->createSequence($seq_name); + if (DB::isError($result)) { + return $this->raiseError($result); + } + } else { + $repeat = 0; + } + } while ($repeat); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $arr = $result->fetchRow(DB_FETCHMODE_ORDERED); + return $arr[0]; + } + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_oci8::nextID(), DB_oci8::dropSequence() + */ + function createSequence($seq_name) + { + return $this->query('CREATE SEQUENCE ' + . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_oci8::nextID(), DB_oci8::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP SEQUENCE ' + . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ oci8RaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_oci8::errorNative(), DB_oci8::errorCode() + */ + function oci8RaiseError($errno = null) + { + if ($errno === null) { + $error = @OCIError($this->connection); + return $this->raiseError($this->errorCode($error['code']), + null, null, null, $error['message']); + } elseif (is_resource($errno)) { + $error = @OCIError($errno); + return $this->raiseError($this->errorCode($error['code']), + null, null, null, $error['message']); + } + return $this->raiseError($this->errorCode($errno)); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code produced by the last query + * + * @return int the DBMS' error code. FALSE if the code could not be + * determined + */ + function errorNative() + { + if (is_resource($this->last_stmt)) { + $error = @OCIError($this->last_stmt); + } else { + $error = @OCIError($this->connection); + } + if (is_array($error)) { + return $error['code']; + } + return false; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * NOTE: flags won't contain index information. + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $res = array(); + + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $result = strtoupper($result); + $q_fields = 'SELECT column_name, data_type, data_length, ' + . 'nullable ' + . 'FROM user_tab_columns ' + . "WHERE table_name='$result' ORDER BY column_id"; + + $this->last_query = $q_fields; + + if (!$stmt = @OCIParse($this->connection, $q_fields)) { + return $this->oci8RaiseError(DB_ERROR_NEED_MORE_DATA); + } + if (!@OCIExecute($stmt, OCI_DEFAULT)) { + return $this->oci8RaiseError($stmt); + } + + $i = 0; + while (@OCIFetch($stmt)) { + $res[$i] = array( + 'table' => $case_func($result), + 'name' => $case_func(@OCIResult($stmt, 1)), + 'type' => @OCIResult($stmt, 2), + 'len' => @OCIResult($stmt, 3), + 'flags' => (@OCIResult($stmt, 4) == 'N') ? 'not_null' : '', + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + $i++; + } + + if ($mode) { + $res['num_fields'] = $i; + } + @OCIFreeStatement($stmt); + + } else { + if (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $result = $result->result; + } + + $res = array(); + + if ($result === $this->last_stmt) { + $count = @OCINumCols($result); + if ($mode) { + $res['num_fields'] = $count; + } + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => '', + 'name' => $case_func(@OCIColumnName($result, $i+1)), + 'type' => @OCIColumnType($result, $i+1), + 'len' => @OCIColumnSize($result, $i+1), + 'flags' => '', + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + } else { + return $this->raiseError(DB_ERROR_NOT_CAPABLE); + } + } + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return 'SELECT table_name FROM user_tables'; + case 'synonyms': + return 'SELECT synonym_name FROM user_synonyms'; + case 'views': + return 'SELECT view_name FROM user_views'; + default: + return null; + } + } + + // }}} + // {{{ quoteFloat() + + /** + * Formats a float value for use within a query in a locale-independent + * manner. + * + * @param float the float value to be quoted. + * @return string the quoted string. + * @see DB_common::quoteSmart() + * @since Method available since release 1.7.8. + */ + function quoteFloat($float) { + return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/odbc.php b/common/PEAR/DB/odbc.php new file mode 100644 index 0000000..c472505 --- /dev/null +++ b/common/PEAR/DB/odbc.php @@ -0,0 +1,883 @@ + + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: odbc.php,v 1.81 2007/07/06 05:19:21 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's odbc extension + * for interacting with databases via ODBC connections + * + * These methods overload the ones declared in DB_common. + * + * More info on ODBC errors could be found here: + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp + * + * @category Database + * @package DB + * @author Stig Bakken + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_odbc extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'odbc'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'sql92'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * NOTE: The feature set of the following drivers are different than + * the default: + * + solid: 'transactions' = true + * + navision: 'limit' = false + * + * @var array + */ + var $features = array( + 'limit' => 'emulate', + 'new_link' => false, + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => false, + 'transactions' => false, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + '01004' => DB_ERROR_TRUNCATED, + '07001' => DB_ERROR_MISMATCH, + '21S01' => DB_ERROR_VALUE_COUNT_ON_ROW, + '21S02' => DB_ERROR_MISMATCH, + '22001' => DB_ERROR_INVALID, + '22003' => DB_ERROR_INVALID_NUMBER, + '22005' => DB_ERROR_INVALID_NUMBER, + '22008' => DB_ERROR_INVALID_DATE, + '22012' => DB_ERROR_DIVZERO, + '23000' => DB_ERROR_CONSTRAINT, + '23502' => DB_ERROR_CONSTRAINT_NOT_NULL, + '23503' => DB_ERROR_CONSTRAINT, + '23504' => DB_ERROR_CONSTRAINT, + '23505' => DB_ERROR_CONSTRAINT, + '24000' => DB_ERROR_INVALID, + '34000' => DB_ERROR_INVALID, + '37000' => DB_ERROR_SYNTAX, + '42000' => DB_ERROR_SYNTAX, + '42601' => DB_ERROR_SYNTAX, + 'IM001' => DB_ERROR_UNSUPPORTED, + 'S0000' => DB_ERROR_NOSUCHTABLE, + 'S0001' => DB_ERROR_ALREADY_EXISTS, + 'S0002' => DB_ERROR_NOSUCHTABLE, + 'S0011' => DB_ERROR_ALREADY_EXISTS, + 'S0012' => DB_ERROR_NOT_FOUND, + 'S0021' => DB_ERROR_ALREADY_EXISTS, + 'S0022' => DB_ERROR_NOSUCHFIELD, + 'S1009' => DB_ERROR_INVALID, + 'S1090' => DB_ERROR_INVALID, + 'S1C00' => DB_ERROR_NOT_CAPABLE, + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * The number of rows affected by a data manipulation query + * @var integer + * @access private + */ + var $affected = 0; + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_odbc() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's odbc driver supports the following extra DSN options: + * + cursor The type of cursor to be used for this connection. + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('odbc')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + switch ($this->dbsyntax) { + case 'access': + case 'db2': + case 'solid': + $this->features['transactions'] = true; + break; + case 'navision': + $this->features['limit'] = false; + } + + /* + * This is hear for backwards compatibility. Should have been using + * 'database' all along, but prior to 1.6.0RC3 'hostspec' was used. + */ + if ($dsn['database']) { + $odbcdsn = $dsn['database']; + } elseif ($dsn['hostspec']) { + $odbcdsn = $dsn['hostspec']; + } else { + $odbcdsn = 'localhost'; + } + + $connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect'; + + if (empty($dsn['cursor'])) { + $this->connection = @$connect_function($odbcdsn, $dsn['username'], + $dsn['password']); + } else { + $this->connection = @$connect_function($odbcdsn, $dsn['username'], + $dsn['password'], + $dsn['cursor']); + } + + if (!is_resource($this->connection)) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $this->errorNative()); + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $err = @odbc_close($this->connection); + $this->connection = null; + return $err; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $this->last_query = $query; + $query = $this->modifyQuery($query); + $result = @odbc_exec($this->connection, $query); + if (!$result) { + return $this->odbcRaiseError(); // XXX ERRORMSG + } + // Determine which queries that should return data, and which + // should return an error code only. + if ($this->_checkManip($query)) { + $this->affected = $result; // For affectedRows() + return DB_OK; + } + $this->affected = 0; + return $result; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal odbc result pointer to the next available result + * + * @param a valid fbsql result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return @odbc_next_result($result); + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + $arr = array(); + if ($rownum !== null) { + $rownum++; // ODBC first row is 1 + if (version_compare(phpversion(), '4.2.0', 'ge')) { + $cols = @odbc_fetch_into($result, $arr, $rownum); + } else { + $cols = @odbc_fetch_into($result, $rownum, $arr); + } + } else { + $cols = @odbc_fetch_into($result, $arr); + } + if (!$cols) { + return null; + } + if ($fetchmode !== DB_FETCHMODE_ORDERED) { + for ($i = 0; $i < count($arr); $i++) { + $colName = @odbc_field_name($result, $i+1); + $a[$colName] = $arr[$i]; + } + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $a = array_change_key_case($a, CASE_LOWER); + } + $arr = $a; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? odbc_free_result($result) : false; + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @odbc_num_fields($result); + if (!$cols) { + return $this->odbcRaiseError(); + } + return $cols; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if (empty($this->affected)) { // In case of SELECT stms + return 0; + } + $nrows = @odbc_num_rows($this->affected); + if ($nrows == -1) { + return $this->odbcRaiseError(); + } + return $nrows; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * Not all ODBC drivers support this functionality. If they don't + * a DB_Error object for DB_ERROR_UNSUPPORTED is returned. + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $nrows = @odbc_num_rows($result); + if ($nrows == -1) { + return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED); + } + if ($nrows === false) { + return $this->odbcRaiseError(); + } + return $nrows; + } + + // }}} + // {{{ quoteIdentifier() + + /** + * Quotes a string so it can be safely used as a table or column name + * + * Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked + * "Use ANSI quoted identifiers" when setting up the ODBC data source. + * + * @param string $str identifier name to be quoted + * + * @return string quoted identifier string + * + * @see DB_common::quoteIdentifier() + * @since Method available since Release 1.6.0 + */ + function quoteIdentifier($str) + { + switch ($this->dsn['dbsyntax']) { + case 'access': + return '[' . $str . ']'; + case 'mssql': + case 'sybase': + return '[' . str_replace(']', ']]', $str) . ']'; + case 'mysql': + case 'mysqli': + return '`' . $str . '`'; + default: + return '"' . str_replace('"', '""', $str) . '"'; + } + } + + // }}} + // {{{ quote() + + /** + * @deprecated Deprecated in release 1.6.0 + * @internal + */ + function quote($str) + { + return $this->quoteSmart($str); + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_odbc::createSequence(), DB_odbc::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + $repeat = 0; + do { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("update ${seqname} set id = id + 1"); + $this->popErrorHandling(); + if ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) { + $repeat = 1; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->createSequence($seq_name); + $this->popErrorHandling(); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $result = $this->query("insert into ${seqname} (id) values(0)"); + } else { + $repeat = 0; + } + } while ($repeat); + + if (DB::isError($result)) { + return $this->raiseError($result); + } + + $result = $this->query("select id from ${seqname}"); + if (DB::isError($result)) { + return $result; + } + + $row = $result->fetchRow(DB_FETCHMODE_ORDERED); + if (DB::isError($row || !$row)) { + return $row; + } + + return $row[0]; + } + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_odbc::nextID(), DB_odbc::dropSequence() + */ + function createSequence($seq_name) + { + return $this->query('CREATE TABLE ' + . $this->getSequenceName($seq_name) + . ' (id integer NOT NULL,' + . ' PRIMARY KEY(id))'); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_odbc::nextID(), DB_odbc::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + if (!@odbc_autocommit($this->connection, $onoff)) { + return $this->odbcRaiseError(); + } + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + if (!@odbc_commit($this->connection)) { + return $this->odbcRaiseError(); + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + if (!@odbc_rollback($this->connection)) { + return $this->odbcRaiseError(); + } + return DB_OK; + } + + // }}} + // {{{ odbcRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_odbc::errorNative(), DB_common::errorCode() + */ + function odbcRaiseError($errno = null) + { + if ($errno === null) { + switch ($this->dbsyntax) { + case 'access': + if ($this->options['portability'] & DB_PORTABILITY_ERRORS) { + $this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD; + } else { + // Doing this in case mode changes during runtime. + $this->errorcode_map['07001'] = DB_ERROR_MISMATCH; + } + + $native_code = odbc_error($this->connection); + + // S1000 is for "General Error." Let's be more specific. + if ($native_code == 'S1000') { + $errormsg = odbc_errormsg($this->connection); + static $error_regexps; + if (!isset($error_regexps)) { + $error_regexps = array( + '/includes related records.$/i' => DB_ERROR_CONSTRAINT, + '/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL, + ); + } + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $errormsg)) { + return $this->raiseError($code, + null, null, null, + $native_code . ' ' . $errormsg); + } + } + $errno = DB_ERROR; + } else { + $errno = $this->errorCode($native_code); + } + break; + default: + $errno = $this->errorCode(odbc_error($this->connection)); + } + } + return $this->raiseError($errno, null, null, null, + $this->errorNative()); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error code and message produced by the last query + * + * @return string the DBMS' error code and message + */ + function errorNative() + { + if (!is_resource($this->connection)) { + return @odbc_error() . ' ' . @odbc_errormsg(); + } + return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection); + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + * @since Method available since Release 1.7.0 + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @odbc_exec($this->connection, "SELECT * FROM $result"); + if (!$id) { + return $this->odbcRaiseError(); + } + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @odbc_num_fields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $col = $i + 1; + $res[$i] = array( + 'table' => $got_string ? $case_func($result) : '', + 'name' => $case_func(@odbc_field_name($id, $col)), + 'type' => @odbc_field_type($id, $col), + 'len' => @odbc_field_len($id, $col), + 'flags' => '', + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @odbc_free_result($id); + } + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com. + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the list of objects requested + * + * @access protected + * @see DB_common::getListOf() + * @since Method available since Release 1.7.0 + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'databases': + if (!function_exists('odbc_data_source')) { + return null; + } + $res = @odbc_data_source($this->connection, SQL_FETCH_FIRST); + if (is_array($res)) { + $out = array($res['server']); + while($res = @odbc_data_source($this->connection, + SQL_FETCH_NEXT)) + { + $out[] = $res['server']; + } + return $out; + } else { + return $this->odbcRaiseError(); + } + break; + case 'tables': + case 'schema.tables': + $keep = 'TABLE'; + break; + case 'views': + $keep = 'VIEW'; + break; + default: + return null; + } + + /* + * Removing non-conforming items in the while loop rather than + * in the odbc_tables() call because some backends choke on this: + * odbc_tables($this->connection, '', '', '', 'TABLE') + */ + $res = @odbc_tables($this->connection); + if (!$res) { + return $this->odbcRaiseError(); + } + $out = array(); + while ($row = odbc_fetch_array($res)) { + if ($row['TABLE_TYPE'] != $keep) { + continue; + } + if ($type == 'schema.tables') { + $out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME']; + } else { + $out[] = $row['TABLE_NAME']; + } + } + return $out; + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/pgsql.php b/common/PEAR/DB/pgsql.php new file mode 100644 index 0000000..7b0bf75 --- /dev/null +++ b/common/PEAR/DB/pgsql.php @@ -0,0 +1,1116 @@ + + * @author Stig Bakken + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: pgsql.php,v 1.138 2007/09/21 13:40:41 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's pgsql extension + * for interacting with PostgreSQL databases + * + * These methods overload the ones declared in DB_common. + * + * @category Database + * @package DB + * @author Rui Hirokawa + * @author Stig Bakken + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_pgsql extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'pgsql'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'pgsql'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'alter', + 'new_link' => '4.3.0', + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => true, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * The quantity of transactions begun + * + * {@internal While this is private, it can't actually be designated + * private in PHP 5 because it is directly accessed in the test suite.}} + * + * @var integer + * @access private + */ + var $transaction_opcount = 0; + + /** + * The number of rows affected by a data manipulation query + * @var integer + */ + var $affected = 0; + + /** + * The current row being looked at in fetchInto() + * @var array + * @access private + */ + var $row = array(); + + /** + * The number of rows in a given result set + * @var array + * @access private + */ + var $_num_rows = array(); + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_pgsql() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's pgsql driver supports the following extra DSN options: + * + connect_timeout How many seconds to wait for a connection to + * be established. Available since PEAR DB 1.7.0. + * + new_link If set to true, causes subsequent calls to + * connect() to return a new connection link + * instead of the existing one. WARNING: this is + * not portable to other DBMS's. Available only + * if PHP is >= 4.3.0 and PEAR DB is >= 1.7.0. + * + options Command line options to be sent to the server. + * Available since PEAR DB 1.6.4. + * + service Specifies a service name in pg_service.conf that + * holds additional connection parameters. + * Available since PEAR DB 1.7.0. + * + sslmode How should SSL be used when connecting? Values: + * disable, allow, prefer or require. + * Available since PEAR DB 1.7.0. + * + tty This was used to specify where to send server + * debug output. Available since PEAR DB 1.6.4. + * + * Example of connecting to a new link via a socket: + * + * require_once 'DB.php'; + * + * $dsn = 'pgsql://user:pass@unix(/tmp)/dbname?new_link=true'; + * $options = array( + * 'portability' => DB_PORTABILITY_ALL, + * ); + * + * $db = DB::connect($dsn, $options); + * if (PEAR::isError($db)) { + * die($db->getMessage()); + * } + * + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @link http://www.postgresql.org/docs/current/static/libpq.html#LIBPQ-CONNECT + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('pgsql')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $protocol = $dsn['protocol'] ? $dsn['protocol'] : 'tcp'; + + $params = array(''); + if ($protocol == 'tcp') { + if ($dsn['hostspec']) { + $params[0] .= 'host=' . $dsn['hostspec']; + } + if ($dsn['port']) { + $params[0] .= ' port=' . $dsn['port']; + } + } elseif ($protocol == 'unix') { + // Allow for pg socket in non-standard locations. + if ($dsn['socket']) { + $params[0] .= 'host=' . $dsn['socket']; + } + if ($dsn['port']) { + $params[0] .= ' port=' . $dsn['port']; + } + } + if ($dsn['database']) { + $params[0] .= ' dbname=\'' . addslashes($dsn['database']) . '\''; + } + if ($dsn['username']) { + $params[0] .= ' user=\'' . addslashes($dsn['username']) . '\''; + } + if ($dsn['password']) { + $params[0] .= ' password=\'' . addslashes($dsn['password']) . '\''; + } + if (!empty($dsn['options'])) { + $params[0] .= ' options=' . $dsn['options']; + } + if (!empty($dsn['tty'])) { + $params[0] .= ' tty=' . $dsn['tty']; + } + if (!empty($dsn['connect_timeout'])) { + $params[0] .= ' connect_timeout=' . $dsn['connect_timeout']; + } + if (!empty($dsn['sslmode'])) { + $params[0] .= ' sslmode=' . $dsn['sslmode']; + } + if (!empty($dsn['service'])) { + $params[0] .= ' service=' . $dsn['service']; + } + + if (isset($dsn['new_link']) + && ($dsn['new_link'] == 'true' || $dsn['new_link'] === true)) + { + if (version_compare(phpversion(), '4.3.0', '>=')) { + $params[] = PGSQL_CONNECT_FORCE_NEW; + } + } + + $connect_function = $persistent ? 'pg_pconnect' : 'pg_connect'; + + $ini = ini_get('track_errors'); + $php_errormsg = ''; + if ($ini) { + $this->connection = @call_user_func_array($connect_function, + $params); + } else { + @ini_set('track_errors', 1); + $this->connection = @call_user_func_array($connect_function, + $params); + @ini_set('track_errors', $ini); + } + + if (!$this->connection) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + $php_errormsg); + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @pg_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = $this->_checkManip($query); + $this->last_query = $query; + $query = $this->modifyQuery($query); + if (!$this->autocommit && $ismanip) { + if ($this->transaction_opcount == 0) { + $result = @pg_exec($this->connection, 'begin;'); + if (!$result) { + return $this->pgsqlRaiseError(); + } + } + $this->transaction_opcount++; + } + $result = @pg_exec($this->connection, $query); + if (!$result) { + return $this->pgsqlRaiseError(); + } + + /* + * Determine whether queries produce affected rows, result or nothing. + * + * This logic was introduced in version 1.1 of the file by ssb, + * though the regex has been modified slightly since then. + * + * PostgreSQL commands: + * ABORT, ALTER, BEGIN, CLOSE, CLUSTER, COMMIT, COPY, + * CREATE, DECLARE, DELETE, DROP TABLE, EXPLAIN, FETCH, + * GRANT, INSERT, LISTEN, LOAD, LOCK, MOVE, NOTIFY, RESET, + * REVOKE, ROLLBACK, SELECT, SELECT INTO, SET, SHOW, + * UNLISTEN, UPDATE, VACUUM + */ + if ($ismanip) { + $this->affected = @pg_affected_rows($result); + return DB_OK; + } elseif (preg_match('/^\s*\(*\s*(SELECT|EXPLAIN|FETCH|SHOW)\s/si', + $query)) + { + $this->row[(int)$result] = 0; // reset the row counter. + $numrows = $this->numRows($result); + if (is_object($numrows)) { + return $numrows; + } + $this->_num_rows[(int)$result] = $numrows; + $this->affected = 0; + return $result; + } else { + $this->affected = 0; + return DB_OK; + } + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal pgsql result pointer to the next available result + * + * @param a valid fbsql result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + $result_int = (int)$result; + $rownum = ($rownum !== null) ? $rownum : $this->row[$result_int]; + if ($rownum >= $this->_num_rows[$result_int]) { + return null; + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @pg_fetch_array($result, $rownum, PGSQL_ASSOC); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @pg_fetch_row($result, $rownum); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + $this->row[$result_int] = ++$rownum; + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + if (is_resource($result)) { + unset($this->row[(int)$result]); + unset($this->_num_rows[(int)$result]); + $this->affected = 0; + return @pg_freeresult($result); + } + return false; + } + + // }}} + // {{{ quote() + + /** + * @deprecated Deprecated in release 1.6.0 + * @internal + */ + function quote($str) + { + return $this->quoteSmart($str); + } + + // }}} + // {{{ quoteBoolean() + + /** + * Formats a boolean value for use within a query in a locale-independent + * manner. + * + * @param boolean the boolean value to be quoted. + * @return string the quoted string. + * @see DB_common::quoteSmart() + * @since Method available since release 1.7.8. + */ + function quoteBoolean($boolean) { + return $boolean ? 'TRUE' : 'FALSE'; + } + + // }}} + // {{{ escapeSimple() + + /** + * Escapes a string according to the current DBMS's standards + * + * {@internal PostgreSQL treats a backslash as an escape character, + * so they are escaped as well. + * + * @param string $str the string to be escaped + * + * @return string the escaped string + * + * @see DB_common::quoteSmart() + * @since Method available since Release 1.6.0 + */ + function escapeSimple($str) + { + if (function_exists('pg_escape_string')) { + /* This fixes an undocumented BC break in PHP 5.2.0 which changed + * the prototype of pg_escape_string. I'm not thrilled about having + * to sniff the PHP version, quite frankly, but it's the only way + * to deal with the problem. Revision 1.331.2.13.2.10 on + * php-src/ext/pgsql/pgsql.c (PHP_5_2 branch) is to blame, for the + * record. */ + if (version_compare(PHP_VERSION, '5.2.0', '>=')) { + return pg_escape_string($this->connection, $str); + } else { + return pg_escape_string($str); + } + } else { + return str_replace("'", "''", str_replace('\\', '\\\\', $str)); + } + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @pg_numfields($result); + if (!$cols) { + return $this->pgsqlRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @pg_numrows($result); + if ($rows === null) { + return $this->pgsqlRaiseError(); + } + return $rows; + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + // XXX if $this->transaction_opcount > 0, we should probably + // issue a warning here. + $this->autocommit = $onoff ? true : false; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + if ($this->transaction_opcount > 0) { + // (disabled) hack to shut up error messages from libpq.a + //@fclose(@fopen("php://stderr", "w")); + $result = @pg_exec($this->connection, 'end;'); + $this->transaction_opcount = 0; + if (!$result) { + return $this->pgsqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + if ($this->transaction_opcount > 0) { + $result = @pg_exec($this->connection, 'abort;'); + $this->transaction_opcount = 0; + if (!$result) { + return $this->pgsqlRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + return $this->affected; + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_pgsql::createSequence(), DB_pgsql::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + $repeat = false; + do { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("SELECT NEXTVAL('${seqname}')"); + $this->popErrorHandling(); + if ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) { + $repeat = true; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->createSequence($seq_name); + $this->popErrorHandling(); + if (DB::isError($result)) { + return $this->raiseError($result); + } + } else { + $repeat = false; + } + } while ($repeat); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $arr = $result->fetchRow(DB_FETCHMODE_ORDERED); + $result->free(); + return $arr[0]; + } + + // }}} + // {{{ createSequence() + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_pgsql::nextID(), DB_pgsql::dropSequence() + */ + function createSequence($seq_name) + { + $seqname = $this->getSequenceName($seq_name); + $result = $this->query("CREATE SEQUENCE ${seqname}"); + return $result; + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_pgsql::nextID(), DB_pgsql::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP SEQUENCE ' + . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + return "$query LIMIT $count OFFSET $from"; + } + + // }}} + // {{{ pgsqlRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_pgsql::errorNative(), DB_pgsql::errorCode() + */ + function pgsqlRaiseError($errno = null) + { + $native = $this->errorNative(); + if (!$native) { + $native = 'Database connection has been lost.'; + $errno = DB_ERROR_CONNECT_FAILED; + } + if ($errno === null) { + $errno = $this->errorCode($native); + } + return $this->raiseError($errno, null, null, null, $native); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error message produced by the last query + * + * {@internal Error messages are used instead of error codes + * in order to support older versions of PostgreSQL.}} + * + * @return string the DBMS' error message + */ + function errorNative() + { + return @pg_errormessage($this->connection); + } + + // }}} + // {{{ errorCode() + + /** + * Determines PEAR::DB error code from the database's text error message. + * + * @param string $errormsg error message returned from the database + * @return integer an error number from a DB error constant + */ + function errorCode($errormsg) + { + static $error_regexps; + if (!isset($error_regexps)) { + $error_regexps = array( + '/column .* (of relation .*)?does not exist/i' + => DB_ERROR_NOSUCHFIELD, + '/(relation|sequence|table).*does not exist|class .* not found/i' + => DB_ERROR_NOSUCHTABLE, + '/index .* does not exist/' + => DB_ERROR_NOT_FOUND, + '/relation .* already exists/i' + => DB_ERROR_ALREADY_EXISTS, + '/(divide|division) by zero$/i' + => DB_ERROR_DIVZERO, + '/pg_atoi: error in .*: can\'t parse /i' + => DB_ERROR_INVALID_NUMBER, + '/invalid input syntax for( type)? (integer|numeric)/i' + => DB_ERROR_INVALID_NUMBER, + '/value .* is out of range for type \w*int/i' + => DB_ERROR_INVALID_NUMBER, + '/integer out of range/i' + => DB_ERROR_INVALID_NUMBER, + '/value too long for type character/i' + => DB_ERROR_INVALID, + '/attribute .* not found|relation .* does not have attribute/i' + => DB_ERROR_NOSUCHFIELD, + '/column .* specified in USING clause does not exist in (left|right) table/i' + => DB_ERROR_NOSUCHFIELD, + '/parser: parse error at or near/i' + => DB_ERROR_SYNTAX, + '/syntax error at/' + => DB_ERROR_SYNTAX, + '/column reference .* is ambiguous/i' + => DB_ERROR_SYNTAX, + '/permission denied/' + => DB_ERROR_ACCESS_VIOLATION, + '/violates not-null constraint/' + => DB_ERROR_CONSTRAINT_NOT_NULL, + '/violates [\w ]+ constraint/' + => DB_ERROR_CONSTRAINT, + '/referential integrity violation/' + => DB_ERROR_CONSTRAINT, + '/more expressions than target columns/i' + => DB_ERROR_VALUE_COUNT_ON_ROW, + ); + } + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $errormsg)) { + return $code; + } + } + // Fall back to DB_ERROR if there was no mapping. + return DB_ERROR; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @pg_exec($this->connection, "SELECT * FROM $result LIMIT 0"); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->pgsqlRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @pg_numfields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $res[$i] = array( + 'table' => $got_string ? $case_func($result) : '', + 'name' => $case_func(@pg_fieldname($id, $i)), + 'type' => @pg_fieldtype($id, $i), + 'len' => @pg_fieldsize($id, $i), + 'flags' => $got_string + ? $this->_pgFieldFlags($id, $i, $result) + : '', + ); + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @pg_freeresult($id); + } + return $res; + } + + // }}} + // {{{ _pgFieldFlags() + + /** + * Get a column's flags + * + * Supports "not_null", "default_value", "primary_key", "unique_key" + * and "multiple_key". The default value is passed through + * rawurlencode() in case there are spaces in it. + * + * @param int $resource the PostgreSQL result identifier + * @param int $num_field the field number + * + * @return string the flags + * + * @access private + */ + function _pgFieldFlags($resource, $num_field, $table_name) + { + $field_name = @pg_fieldname($resource, $num_field); + + // Check if there's a schema in $table_name and update things + // accordingly. + $from = 'pg_attribute f, pg_class tab, pg_type typ'; + if (strpos($table_name, '.') !== false) { + $from .= ', pg_namespace nsp'; + list($schema, $table) = explode('.', $table_name); + $tableWhere = "tab.relname = '$table' AND tab.relnamespace = nsp.oid AND nsp.nspname = '$schema'"; + } else { + $tableWhere = "tab.relname = '$table_name'"; + } + + $result = @pg_exec($this->connection, "SELECT f.attnotnull, f.atthasdef + FROM $from + WHERE tab.relname = typ.typname + AND typ.typrelid = f.attrelid + AND f.attname = '$field_name' + AND $tableWhere"); + if (@pg_numrows($result) > 0) { + $row = @pg_fetch_row($result, 0); + $flags = ($row[0] == 't') ? 'not_null ' : ''; + + if ($row[1] == 't') { + $result = @pg_exec($this->connection, "SELECT a.adsrc + FROM $from, pg_attrdef a + WHERE tab.relname = typ.typname AND typ.typrelid = f.attrelid + AND f.attrelid = a.adrelid AND f.attname = '$field_name' + AND $tableWhere AND f.attnum = a.adnum"); + $row = @pg_fetch_row($result, 0); + $num = preg_replace("/'(.*)'::\w+/", "\\1", $row[0]); + $flags .= 'default_' . rawurlencode($num) . ' '; + } + } else { + $flags = ''; + } + $result = @pg_exec($this->connection, "SELECT i.indisunique, i.indisprimary, i.indkey + FROM $from, pg_index i + WHERE tab.relname = typ.typname + AND typ.typrelid = f.attrelid + AND f.attrelid = i.indrelid + AND f.attname = '$field_name' + AND $tableWhere"); + $count = @pg_numrows($result); + + for ($i = 0; $i < $count ; $i++) { + $row = @pg_fetch_row($result, $i); + $keys = explode(' ', $row[2]); + + if (in_array($num_field + 1, $keys)) { + $flags .= ($row[0] == 't' && $row[1] == 'f') ? 'unique_key ' : ''; + $flags .= ($row[1] == 't') ? 'primary_key ' : ''; + if (count($keys) > 1) + $flags .= 'multiple_key '; + } + } + + return trim($flags); + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return 'SELECT c.relname AS "Name"' + . ' FROM pg_class c, pg_user u' + . ' WHERE c.relowner = u.usesysid' + . " AND c.relkind = 'r'" + . ' AND NOT EXISTS' + . ' (SELECT 1 FROM pg_views' + . ' WHERE viewname = c.relname)' + . " AND c.relname !~ '^(pg_|sql_)'" + . ' UNION' + . ' SELECT c.relname AS "Name"' + . ' FROM pg_class c' + . " WHERE c.relkind = 'r'" + . ' AND NOT EXISTS' + . ' (SELECT 1 FROM pg_views' + . ' WHERE viewname = c.relname)' + . ' AND NOT EXISTS' + . ' (SELECT 1 FROM pg_user' + . ' WHERE usesysid = c.relowner)' + . " AND c.relname !~ '^pg_'"; + case 'schema.tables': + return "SELECT schemaname || '.' || tablename" + . ' AS "Name"' + . ' FROM pg_catalog.pg_tables' + . ' WHERE schemaname NOT IN' + . " ('pg_catalog', 'information_schema', 'pg_toast')"; + case 'schema.views': + return "SELECT schemaname || '.' || viewname from pg_views WHERE schemaname" + . " NOT IN ('information_schema', 'pg_catalog')"; + case 'views': + // Table cols: viewname | viewowner | definition + return 'SELECT viewname from pg_views WHERE schemaname' + . " NOT IN ('information_schema', 'pg_catalog')"; + case 'users': + // cols: usename |usesysid|usecreatedb|usetrace|usesuper|usecatupd|passwd |valuntil + return 'SELECT usename FROM pg_user'; + case 'databases': + return 'SELECT datname FROM pg_database'; + case 'functions': + case 'procedures': + return 'SELECT proname FROM pg_proc WHERE proowner <> 1'; + default: + return null; + } + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/sqlite.php b/common/PEAR/DB/sqlite.php new file mode 100644 index 0000000..9dfe6cb --- /dev/null +++ b/common/PEAR/DB/sqlite.php @@ -0,0 +1,959 @@ + + * @author Mika Tuupola + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 3.0 + * @version CVS: $Id: sqlite.php,v 1.117 2007/09/21 14:23:28 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's sqlite extension + * for interacting with SQLite databases + * + * These methods overload the ones declared in DB_common. + * + * NOTICE: This driver needs PHP's track_errors ini setting to be on. + * It is automatically turned on when connecting to the database. + * Make sure your scripts don't turn it off. + * + * @category Database + * @package DB + * @author Urs Gehrig + * @author Mika Tuupola + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_sqlite extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'sqlite'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'sqlite'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'alter', + 'new_link' => false, + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => false, + 'transactions' => false, + ); + + /** + * A mapping of native error codes to DB error codes + * + * {@internal Error codes according to sqlite_exec. See the online + * manual at http://sqlite.org/c_interface.html for info. + * This error handling based on sqlite_exec is not yet implemented.}} + * + * @var array + */ + var $errorcode_map = array( + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * SQLite data types + * + * @link http://www.sqlite.org/datatypes.html + * + * @var array + */ + var $keywords = array ( + 'BLOB' => '', + 'BOOLEAN' => '', + 'CHARACTER' => '', + 'CLOB' => '', + 'FLOAT' => '', + 'INTEGER' => '', + 'KEY' => '', + 'NATIONAL' => '', + 'NUMERIC' => '', + 'NVARCHAR' => '', + 'PRIMARY' => '', + 'TEXT' => '', + 'TIMESTAMP' => '', + 'UNIQUE' => '', + 'VARCHAR' => '', + 'VARYING' => '', + ); + + /** + * The most recent error message from $php_errormsg + * @var string + * @access private + */ + var $_lasterror = ''; + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_sqlite() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's sqlite driver supports the following extra DSN options: + * + mode The permissions for the database file, in four digit + * chmod octal format (eg "0600"). + * + * Example of connecting to a database in read-only mode: + * + * require_once 'DB.php'; + * + * $dsn = 'sqlite:///path/and/name/of/db/file?mode=0400'; + * $options = array( + * 'portability' => DB_PORTABILITY_ALL, + * ); + * + * $db = DB::connect($dsn, $options); + * if (PEAR::isError($db)) { + * die($db->getMessage()); + * } + * + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('sqlite')) { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + if (!$dsn['database']) { + return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION); + } + + if ($dsn['database'] !== ':memory:') { + if (!file_exists($dsn['database'])) { + if (!touch($dsn['database'])) { + return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND); + } + if (!isset($dsn['mode']) || + !is_numeric($dsn['mode'])) + { + $mode = 0644; + } else { + $mode = octdec($dsn['mode']); + } + if (!chmod($dsn['database'], $mode)) { + return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND); + } + if (!file_exists($dsn['database'])) { + return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND); + } + } + if (!is_file($dsn['database'])) { + return $this->sqliteRaiseError(DB_ERROR_INVALID); + } + if (!is_readable($dsn['database'])) { + return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION); + } + } + + $connect_function = $persistent ? 'sqlite_popen' : 'sqlite_open'; + + // track_errors must remain on for simpleQuery() + @ini_set('track_errors', 1); + $php_errormsg = ''; + + if (!$this->connection = @$connect_function($dsn['database'])) { + return $this->raiseError(DB_ERROR_NODBSELECTED, + null, null, null, + $php_errormsg); + } + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @sqlite_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * NOTICE: This method needs PHP's track_errors ini setting to be on. + * It is automatically turned on when connecting to the database. + * Make sure your scripts don't turn it off. + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = $this->_checkManip($query); + $this->last_query = $query; + $query = $this->modifyQuery($query); + + $php_errormsg = ''; + + $result = @sqlite_query($query, $this->connection); + $this->_lasterror = $php_errormsg ? $php_errormsg : ''; + + $this->result = $result; + if (!$this->result) { + return $this->sqliteRaiseError(null); + } + + // sqlite_query() seems to allways return a resource + // so cant use that. Using $ismanip instead + if (!$ismanip) { + $numRows = $this->numRows($result); + if (is_object($numRows)) { + // we've got PEAR_Error + return $numRows; + } + return $result; + } + return DB_OK; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal sqlite result pointer to the next available result + * + * @param resource $result the valid sqlite result resource + * + * @return bool true if a result is available otherwise return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + if (!@sqlite_seek($this->result, $rownum)) { + return null; + } + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + $arr = @sqlite_fetch_array($result, SQLITE_ASSOC); + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + + /* Remove extraneous " characters from the fields in the result. + * Fixes bug #11716. */ + if (is_array($arr) && count($arr) > 0) { + $strippedArr = array(); + foreach ($arr as $field => $value) { + $strippedArr[trim($field, '"')] = $value; + } + $arr = $strippedArr; + } + } else { + $arr = @sqlite_fetch_array($result, SQLITE_NUM); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + /* + * Even though this DBMS already trims output, we do this because + * a field might have intentional whitespace at the end that + * gets removed by DB_PORTABILITY_RTRIM under another driver. + */ + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult(&$result) + { + // XXX No native free? + if (!is_resource($result)) { + return false; + } + $result = null; + return true; + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @sqlite_num_fields($result); + if (!$cols) { + return $this->sqliteRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @sqlite_num_rows($result); + if ($rows === null) { + return $this->sqliteRaiseError(); + } + return $rows; + } + + // }}} + // {{{ affected() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + return @sqlite_changes($this->connection); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_sqlite::nextID(), DB_sqlite::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); + } + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_sqlite::nextID(), DB_sqlite::dropSequence() + */ + function createSequence($seq_name) + { + $seqname = $this->getSequenceName($seq_name); + $query = 'CREATE TABLE ' . $seqname . + ' (id INTEGER UNSIGNED PRIMARY KEY) '; + $result = $this->query($query); + if (DB::isError($result)) { + return($result); + } + $query = "CREATE TRIGGER ${seqname}_cleanup AFTER INSERT ON $seqname + BEGIN + DELETE FROM $seqname WHERE idquery($query); + if (DB::isError($result)) { + return($result); + } + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_sqlite::createSequence(), DB_sqlite::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + + do { + $repeat = 0; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("INSERT INTO $seqname (id) VALUES (NULL)"); + $this->popErrorHandling(); + if ($result === DB_OK) { + $id = @sqlite_last_insert_rowid($this->connection); + if ($id != 0) { + return $id; + } + } elseif ($ondemand && DB::isError($result) && + $result->getCode() == DB_ERROR_NOSUCHTABLE) + { + $result = $this->createSequence($seq_name); + if (DB::isError($result)) { + return $this->raiseError($result); + } else { + $repeat = 1; + } + } + } while ($repeat); + + return $this->raiseError($result); + } + + // }}} + // {{{ getDbFileStats() + + /** + * Get the file stats for the current database + * + * Possible arguments are dev, ino, mode, nlink, uid, gid, rdev, size, + * atime, mtime, ctime, blksize, blocks or a numeric key between + * 0 and 12. + * + * @param string $arg the array key for stats() + * + * @return mixed an array on an unspecified key, integer on a passed + * arg and false at a stats error + */ + function getDbFileStats($arg = '') + { + $stats = stat($this->dsn['database']); + if ($stats == false) { + return false; + } + if (is_array($stats)) { + if (is_numeric($arg)) { + if (((int)$arg <= 12) & ((int)$arg >= 0)) { + return false; + } + return $stats[$arg ]; + } + if (array_key_exists(trim($arg), $stats)) { + return $stats[$arg ]; + } + } + return $stats; + } + + // }}} + // {{{ escapeSimple() + + /** + * Escapes a string according to the current DBMS's standards + * + * In SQLite, this makes things safe for inserts/updates, but may + * cause problems when performing text comparisons against columns + * containing binary data. See the + * {@link http://php.net/sqlite_escape_string PHP manual} for more info. + * + * @param string $str the string to be escaped + * + * @return string the escaped string + * + * @since Method available since Release 1.6.1 + * @see DB_common::escapeSimple() + */ + function escapeSimple($str) + { + return @sqlite_escape_string($str); + } + + // }}} + // {{{ modifyLimitQuery() + + /** + * Adds LIMIT clauses to a query string according to current DBMS standards + * + * @param string $query the query to modify + * @param int $from the row to start to fetching (0 = the first row) + * @param int $count the numbers of rows to fetch + * @param mixed $params array, string or numeric data to be used in + * execution of the statement. Quantity of items + * passed must match quantity of placeholders in + * query: meaning 1 placeholder for non-array + * parameters or 1 placeholder per array element. + * + * @return string the query string with LIMIT clauses added + * + * @access protected + */ + function modifyLimitQuery($query, $from, $count, $params = array()) + { + return "$query LIMIT $count OFFSET $from"; + } + + // }}} + // {{{ modifyQuery() + + /** + * Changes a query string for various DBMS specific reasons + * + * This little hack lets you know how many rows were deleted + * when running a "DELETE FROM table" query. Only implemented + * if the DB_PORTABILITY_DELETE_COUNT portability option is on. + * + * @param string $query the query string to modify + * + * @return string the modified query string + * + * @access protected + * @see DB_common::setOption() + */ + function modifyQuery($query) + { + if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) { + if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) { + $query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/', + 'DELETE FROM \1 WHERE 1=1', $query); + } + } + return $query; + } + + // }}} + // {{{ sqliteRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_sqlite::errorNative(), DB_sqlite::errorCode() + */ + function sqliteRaiseError($errno = null) + { + $native = $this->errorNative(); + if ($errno === null) { + $errno = $this->errorCode($native); + } + + $errorcode = @sqlite_last_error($this->connection); + $userinfo = "$errorcode ** $this->last_query"; + + return $this->raiseError($errno, null, null, $userinfo, $native); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error message produced by the last query + * + * {@internal This is used to retrieve more meaningfull error messages + * because sqlite_last_error() does not provide adequate info.}} + * + * @return string the DBMS' error message + */ + function errorNative() + { + return $this->_lasterror; + } + + // }}} + // {{{ errorCode() + + /** + * Determines PEAR::DB error code from the database's text error message + * + * @param string $errormsg the error message returned from the database + * + * @return integer the DB error number + */ + function errorCode($errormsg) + { + static $error_regexps; + + // PHP 5.2+ prepends the function name to $php_errormsg, so we need + // this hack to work around it, per bug #9599. + $errormsg = preg_replace('/^sqlite[a-z_]+\(\): /', '', $errormsg); + + if (!isset($error_regexps)) { + $error_regexps = array( + '/^no such table:/' => DB_ERROR_NOSUCHTABLE, + '/^no such index:/' => DB_ERROR_NOT_FOUND, + '/^(table|index) .* already exists$/' => DB_ERROR_ALREADY_EXISTS, + '/PRIMARY KEY must be unique/i' => DB_ERROR_CONSTRAINT, + '/is not unique/' => DB_ERROR_CONSTRAINT, + '/columns .* are not unique/i' => DB_ERROR_CONSTRAINT, + '/uniqueness constraint failed/' => DB_ERROR_CONSTRAINT, + '/may not be NULL/' => DB_ERROR_CONSTRAINT_NOT_NULL, + '/^no such column:/' => DB_ERROR_NOSUCHFIELD, + '/column not present in both tables/i' => DB_ERROR_NOSUCHFIELD, + '/^near ".*": syntax error$/' => DB_ERROR_SYNTAX, + '/[0-9]+ values for [0-9]+ columns/i' => DB_ERROR_VALUE_COUNT_ON_ROW, + ); + } + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $errormsg)) { + return $code; + } + } + // Fall back to DB_ERROR if there was no mapping. + return DB_ERROR; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table + * + * @param string $result a string containing the name of a table + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + * @since Method available since Release 1.7.0 + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + $id = @sqlite_array_query($this->connection, + "PRAGMA table_info('$result');", + SQLITE_ASSOC); + $got_string = true; + } else { + $this->last_query = ''; + return $this->raiseError(DB_ERROR_NOT_CAPABLE, null, null, null, + 'This DBMS can not obtain tableInfo' . + ' from result sets'); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = count($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + if (strpos($id[$i]['type'], '(') !== false) { + $bits = explode('(', $id[$i]['type']); + $type = $bits[0]; + $len = rtrim($bits[1],')'); + } else { + $type = $id[$i]['type']; + $len = 0; + } + + $flags = ''; + if ($id[$i]['pk']) { + $flags .= 'primary_key '; + } + if ($id[$i]['notnull']) { + $flags .= 'not_null '; + } + if ($id[$i]['dflt_value'] !== null) { + $flags .= 'default_' . rawurlencode($id[$i]['dflt_value']); + } + $flags = trim($flags); + + $res[$i] = array( + 'table' => $case_func($result), + 'name' => $case_func($id[$i]['name']), + 'type' => $type, + 'len' => $len, + 'flags' => $flags, + ); + + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + return $res; + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * @param array $args SQLITE DRIVER ONLY: a private array of arguments + * used by the getSpecialQuery(). Do not use + * this directly. + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type, $args = array()) + { + if (!is_array($args)) { + return $this->raiseError('no key specified', null, null, null, + 'Argument has to be an array.'); + } + + switch ($type) { + case 'master': + return 'SELECT * FROM sqlite_master;'; + case 'tables': + return "SELECT name FROM sqlite_master WHERE type='table' " + . 'UNION ALL SELECT name FROM sqlite_temp_master ' + . "WHERE type='table' ORDER BY name;"; + case 'schema': + return 'SELECT sql FROM (SELECT * FROM sqlite_master ' + . 'UNION ALL SELECT * FROM sqlite_temp_master) ' + . "WHERE type!='meta' " + . 'ORDER BY tbl_name, type DESC, name;'; + case 'schemax': + case 'schema_x': + /* + * Use like: + * $res = $db->query($db->getSpecialQuery('schema_x', + * array('table' => 'table3'))); + */ + return 'SELECT sql FROM (SELECT * FROM sqlite_master ' + . 'UNION ALL SELECT * FROM sqlite_temp_master) ' + . "WHERE tbl_name LIKE '{$args['table']}' " + . "AND type!='meta' " + . 'ORDER BY type DESC, name;'; + case 'alter': + /* + * SQLite does not support ALTER TABLE; this is a helper query + * to handle this. 'table' represents the table name, 'rows' + * the news rows to create, 'save' the row(s) to keep _with_ + * the data. + * + * Use like: + * $args = array( + * 'table' => $table, + * 'rows' => "id INTEGER PRIMARY KEY, firstname TEXT, surname TEXT, datetime TEXT", + * 'save' => "NULL, titel, content, datetime" + * ); + * $res = $db->query( $db->getSpecialQuery('alter', $args)); + */ + $rows = strtr($args['rows'], $this->keywords); + + $q = array( + 'BEGIN TRANSACTION', + "CREATE TEMPORARY TABLE {$args['table']}_backup ({$args['rows']})", + "INSERT INTO {$args['table']}_backup SELECT {$args['save']} FROM {$args['table']}", + "DROP TABLE {$args['table']}", + "CREATE TABLE {$args['table']} ({$args['rows']})", + "INSERT INTO {$args['table']} SELECT {$rows} FROM {$args['table']}_backup", + "DROP TABLE {$args['table']}_backup", + 'COMMIT', + ); + + /* + * This is a dirty hack, since the above query will not get + * executed with a single query call so here the query method + * will be called directly and return a select instead. + */ + foreach ($q as $query) { + $this->query($query); + } + return "SELECT * FROM {$args['table']};"; + default: + return null; + } + } + + // }}} +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/storage.php b/common/PEAR/DB/storage.php new file mode 100644 index 0000000..56afdea --- /dev/null +++ b/common/PEAR/DB/storage.php @@ -0,0 +1,506 @@ + + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: storage.php,v 1.24 2007/08/12 05:27:25 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB class so it can be extended from + */ +require_once 'DB.php'; + +/** + * Provides an object interface to a table row + * + * It lets you add, delete and change rows using objects rather than SQL + * statements. + * + * @category Database + * @package DB + * @author Stig Bakken + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_storage extends PEAR +{ + // {{{ properties + + /** the name of the table (or view, if the backend database supports + updates in views) we hold data from */ + var $_table = null; + + /** which column(s) in the table contains primary keys, can be a + string for single-column primary keys, or an array of strings + for multiple-column primary keys */ + var $_keycolumn = null; + + /** DB connection handle used for all transactions */ + var $_dbh = null; + + /** an assoc with the names of database fields stored as properties + in this object */ + var $_properties = array(); + + /** an assoc with the names of the properties in this object that + have been changed since they were fetched from the database */ + var $_changes = array(); + + /** flag that decides if data in this object can be changed. + objects that don't have their table's key column in their + property lists will be flagged as read-only. */ + var $_readonly = false; + + /** function or method that implements a validator for fields that + are set, this validator function returns true if the field is + valid, false if not */ + var $_validator = null; + + // }}} + // {{{ constructor + + /** + * Constructor + * + * @param $table string the name of the database table + * + * @param $keycolumn mixed string with name of key column, or array of + * strings if the table has a primary key of more than one column + * + * @param $dbh object database connection object + * + * @param $validator mixed function or method used to validate + * each new value, called with three parameters: the name of the + * field/column that is changing, a reference to the new value and + * a reference to this object + * + */ + function DB_storage($table, $keycolumn, &$dbh, $validator = null) + { + $this->PEAR('DB_Error'); + $this->_table = $table; + $this->_keycolumn = $keycolumn; + $this->_dbh = $dbh; + $this->_readonly = false; + $this->_validator = $validator; + } + + // }}} + // {{{ _makeWhere() + + /** + * Utility method to build a "WHERE" clause to locate ourselves in + * the table. + * + * XXX future improvement: use rowids? + * + * @access private + */ + function _makeWhere($keyval = null) + { + if (is_array($this->_keycolumn)) { + if ($keyval === null) { + for ($i = 0; $i < sizeof($this->_keycolumn); $i++) { + $keyval[] = $this->{$this->_keycolumn[$i]}; + } + } + $whereclause = ''; + for ($i = 0; $i < sizeof($this->_keycolumn); $i++) { + if ($i > 0) { + $whereclause .= ' AND '; + } + $whereclause .= $this->_keycolumn[$i]; + if (is_null($keyval[$i])) { + // there's not much point in having a NULL key, + // but we support it anyway + $whereclause .= ' IS NULL'; + } else { + $whereclause .= ' = ' . $this->_dbh->quote($keyval[$i]); + } + } + } else { + if ($keyval === null) { + $keyval = @$this->{$this->_keycolumn}; + } + $whereclause = $this->_keycolumn; + if (is_null($keyval)) { + // there's not much point in having a NULL key, + // but we support it anyway + $whereclause .= ' IS NULL'; + } else { + $whereclause .= ' = ' . $this->_dbh->quote($keyval); + } + } + return $whereclause; + } + + // }}} + // {{{ setup() + + /** + * Method used to initialize a DB_storage object from the + * configured table. + * + * @param $keyval mixed the key[s] of the row to fetch (string or array) + * + * @return int DB_OK on success, a DB error if not + */ + function setup($keyval) + { + $whereclause = $this->_makeWhere($keyval); + $query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . $whereclause; + $sth = $this->_dbh->query($query); + if (DB::isError($sth)) { + return $sth; + } + $row = $sth->fetchRow(DB_FETCHMODE_ASSOC); + if (DB::isError($row)) { + return $row; + } + if (!$row) { + return $this->raiseError(null, DB_ERROR_NOT_FOUND, null, null, + $query, null, true); + } + foreach ($row as $key => $value) { + $this->_properties[$key] = true; + $this->$key = $value; + } + return DB_OK; + } + + // }}} + // {{{ insert() + + /** + * Create a new (empty) row in the configured table for this + * object. + */ + function insert($newpk) + { + if (is_array($this->_keycolumn)) { + $primarykey = $this->_keycolumn; + } else { + $primarykey = array($this->_keycolumn); + } + settype($newpk, "array"); + for ($i = 0; $i < sizeof($primarykey); $i++) { + $pkvals[] = $this->_dbh->quote($newpk[$i]); + } + + $sth = $this->_dbh->query("INSERT INTO $this->_table (" . + implode(",", $primarykey) . ") VALUES(" . + implode(",", $pkvals) . ")"); + if (DB::isError($sth)) { + return $sth; + } + if (sizeof($newpk) == 1) { + $newpk = $newpk[0]; + } + $this->setup($newpk); + } + + // }}} + // {{{ toString() + + /** + * Output a simple description of this DB_storage object. + * @return string object description + */ + function toString() + { + $info = strtolower(get_class($this)); + $info .= " (table="; + $info .= $this->_table; + $info .= ", keycolumn="; + if (is_array($this->_keycolumn)) { + $info .= "(" . implode(",", $this->_keycolumn) . ")"; + } else { + $info .= $this->_keycolumn; + } + $info .= ", dbh="; + if (is_object($this->_dbh)) { + $info .= $this->_dbh->toString(); + } else { + $info .= "null"; + } + $info .= ")"; + if (sizeof($this->_properties)) { + $info .= " [loaded, key="; + $keyname = $this->_keycolumn; + if (is_array($keyname)) { + $info .= "("; + for ($i = 0; $i < sizeof($keyname); $i++) { + if ($i > 0) { + $info .= ","; + } + $info .= $this->$keyname[$i]; + } + $info .= ")"; + } else { + $info .= $this->$keyname; + } + $info .= "]"; + } + if (sizeof($this->_changes)) { + $info .= " [modified]"; + } + return $info; + } + + // }}} + // {{{ dump() + + /** + * Dump the contents of this object to "standard output". + */ + function dump() + { + foreach ($this->_properties as $prop => $foo) { + print "$prop = "; + print htmlentities($this->$prop); + print "
\n"; + } + } + + // }}} + // {{{ &create() + + /** + * Static method used to create new DB storage objects. + * @param $data assoc. array where the keys are the names + * of properties/columns + * @return object a new instance of DB_storage or a subclass of it + */ + function &create($table, &$data) + { + $classname = strtolower(get_class($this)); + $obj = new $classname($table); + foreach ($data as $name => $value) { + $obj->_properties[$name] = true; + $obj->$name = &$value; + } + return $obj; + } + + // }}} + // {{{ loadFromQuery() + + /** + * Loads data into this object from the given query. If this + * object already contains table data, changes will be saved and + * the object re-initialized first. + * + * @param $query SQL query + * + * @param $params parameter list in case you want to use + * prepare/execute mode + * + * @return int DB_OK on success, DB_WARNING_READ_ONLY if the + * returned object is read-only (because the object's specified + * key column was not found among the columns returned by $query), + * or another DB error code in case of errors. + */ +// XXX commented out for now +/* + function loadFromQuery($query, $params = null) + { + if (sizeof($this->_properties)) { + if (sizeof($this->_changes)) { + $this->store(); + $this->_changes = array(); + } + $this->_properties = array(); + } + $rowdata = $this->_dbh->getRow($query, DB_FETCHMODE_ASSOC, $params); + if (DB::isError($rowdata)) { + return $rowdata; + } + reset($rowdata); + $found_keycolumn = false; + while (list($key, $value) = each($rowdata)) { + if ($key == $this->_keycolumn) { + $found_keycolumn = true; + } + $this->_properties[$key] = true; + $this->$key = &$value; + unset($value); // have to unset, or all properties will + // refer to the same value + } + if (!$found_keycolumn) { + $this->_readonly = true; + return DB_WARNING_READ_ONLY; + } + return DB_OK; + } + */ + + // }}} + // {{{ set() + + /** + * Modify an attriute value. + */ + function set($property, $newvalue) + { + // only change if $property is known and object is not + // read-only + if ($this->_readonly) { + return $this->raiseError(null, DB_WARNING_READ_ONLY, null, + null, null, null, true); + } + if (@isset($this->_properties[$property])) { + if (empty($this->_validator)) { + $valid = true; + } else { + $valid = @call_user_func($this->_validator, + $this->_table, + $property, + $newvalue, + $this->$property, + $this); + } + if ($valid) { + $this->$property = $newvalue; + if (empty($this->_changes[$property])) { + $this->_changes[$property] = 0; + } else { + $this->_changes[$property]++; + } + } else { + return $this->raiseError(null, DB_ERROR_INVALID, null, + null, "invalid field: $property", + null, true); + } + return true; + } + return $this->raiseError(null, DB_ERROR_NOSUCHFIELD, null, + null, "unknown field: $property", + null, true); + } + + // }}} + // {{{ &get() + + /** + * Fetch an attribute value. + * + * @param string attribute name + * + * @return attribute contents, or null if the attribute name is + * unknown + */ + function &get($property) + { + // only return if $property is known + if (isset($this->_properties[$property])) { + return $this->$property; + } + $tmp = null; + return $tmp; + } + + // }}} + // {{{ _DB_storage() + + /** + * Destructor, calls DB_storage::store() if there are changes + * that are to be kept. + */ + function _DB_storage() + { + if (sizeof($this->_changes)) { + $this->store(); + } + $this->_properties = array(); + $this->_changes = array(); + $this->_table = null; + } + + // }}} + // {{{ store() + + /** + * Stores changes to this object in the database. + * + * @return DB_OK or a DB error + */ + function store() + { + $params = array(); + $vars = array(); + foreach ($this->_changes as $name => $foo) { + $params[] = &$this->$name; + $vars[] = $name . ' = ?'; + } + if ($vars) { + $query = 'UPDATE ' . $this->_table . ' SET ' . + implode(', ', $vars) . ' WHERE ' . + $this->_makeWhere(); + $stmt = $this->_dbh->prepare($query); + $res = $this->_dbh->execute($stmt, $params); + if (DB::isError($res)) { + return $res; + } + $this->_changes = array(); + } + return DB_OK; + } + + // }}} + // {{{ remove() + + /** + * Remove the row represented by this object from the database. + * + * @return mixed DB_OK or a DB error + */ + function remove() + { + if ($this->_readonly) { + return $this->raiseError(null, DB_WARNING_READ_ONLY, null, + null, null, null, true); + } + $query = 'DELETE FROM ' . $this->_table .' WHERE '. + $this->_makeWhere(); + $res = $this->_dbh->query($query); + if (DB::isError($res)) { + return $res; + } + foreach ($this->_properties as $prop => $foo) { + unset($this->$prop); + } + $this->_properties = array(); + $this->_changes = array(); + return DB_OK; + } + + // }}} +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/DB/sybase.php b/common/PEAR/DB/sybase.php new file mode 100644 index 0000000..15a3a93 --- /dev/null +++ b/common/PEAR/DB/sybase.php @@ -0,0 +1,942 @@ + + * @author Antnio Carlos Venncio Jnior + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: sybase.php,v 1.87 2007/09/21 13:40:42 aharvey Exp $ + * @link http://pear.php.net/package/DB + */ + +/** + * Obtain the DB_common class so it can be extended from + */ +require_once 'DB/common.php'; + +/** + * The methods PEAR DB uses to interact with PHP's sybase extension + * for interacting with Sybase databases + * + * These methods overload the ones declared in DB_common. + * + * WARNING: This driver may fail with multiple connections under the + * same user/pass/host and different databases. + * + * @category Database + * @package DB + * @author Sterling Hughes + * @author Antnio Carlos Venncio Jnior + * @author Daniel Convissor + * @copyright 1997-2007 The PHP Group + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version Release: 1.7.13 + * @link http://pear.php.net/package/DB + */ +class DB_sybase extends DB_common +{ + // {{{ properties + + /** + * The DB driver type (mysql, oci8, odbc, etc.) + * @var string + */ + var $phptype = 'sybase'; + + /** + * The database syntax variant to be used (db2, access, etc.), if any + * @var string + */ + var $dbsyntax = 'sybase'; + + /** + * The capabilities of this DB implementation + * + * The 'new_link' element contains the PHP version that first provided + * new_link support for this DBMS. Contains false if it's unsupported. + * + * Meaning of the 'limit' element: + * + 'emulate' = emulate with fetch row by number + * + 'alter' = alter the query + * + false = skip rows + * + * @var array + */ + var $features = array( + 'limit' => 'emulate', + 'new_link' => false, + 'numrows' => true, + 'pconnect' => true, + 'prepare' => false, + 'ssl' => false, + 'transactions' => true, + ); + + /** + * A mapping of native error codes to DB error codes + * @var array + */ + var $errorcode_map = array( + ); + + /** + * The raw database connection created by PHP + * @var resource + */ + var $connection; + + /** + * The DSN information for connecting to a database + * @var array + */ + var $dsn = array(); + + + /** + * Should data manipulation queries be committed automatically? + * @var bool + * @access private + */ + var $autocommit = true; + + /** + * The quantity of transactions begun + * + * {@internal While this is private, it can't actually be designated + * private in PHP 5 because it is directly accessed in the test suite.}} + * + * @var integer + * @access private + */ + var $transaction_opcount = 0; + + /** + * The database specified in the DSN + * + * It's a fix to allow calls to different databases in the same script. + * + * @var string + * @access private + */ + var $_db = ''; + + + // }}} + // {{{ constructor + + /** + * This constructor calls $this->DB_common() + * + * @return void + */ + function DB_sybase() + { + $this->DB_common(); + } + + // }}} + // {{{ connect() + + /** + * Connect to the database server, log in and open the database + * + * Don't call this method directly. Use DB::connect() instead. + * + * PEAR DB's sybase driver supports the following extra DSN options: + * + appname The application name to use on this connection. + * Available since PEAR DB 1.7.0. + * + charset The character set to use on this connection. + * Available since PEAR DB 1.7.0. + * + * @param array $dsn the data source name + * @param bool $persistent should the connection be persistent? + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function connect($dsn, $persistent = false) + { + if (!PEAR::loadExtension('sybase') && + !PEAR::loadExtension('sybase_ct')) + { + return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND); + } + + $this->dsn = $dsn; + if ($dsn['dbsyntax']) { + $this->dbsyntax = $dsn['dbsyntax']; + } + + $dsn['hostspec'] = $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost'; + $dsn['password'] = !empty($dsn['password']) ? $dsn['password'] : false; + $dsn['charset'] = isset($dsn['charset']) ? $dsn['charset'] : false; + $dsn['appname'] = isset($dsn['appname']) ? $dsn['appname'] : false; + + $connect_function = $persistent ? 'sybase_pconnect' : 'sybase_connect'; + + if ($dsn['username']) { + $this->connection = @$connect_function($dsn['hostspec'], + $dsn['username'], + $dsn['password'], + $dsn['charset'], + $dsn['appname']); + } else { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + 'The DSN did not contain a username.'); + } + + if (!$this->connection) { + return $this->raiseError(DB_ERROR_CONNECT_FAILED, + null, null, null, + @sybase_get_last_message()); + } + + if ($dsn['database']) { + if (!@sybase_select_db($dsn['database'], $this->connection)) { + return $this->raiseError(DB_ERROR_NODBSELECTED, + null, null, null, + @sybase_get_last_message()); + } + $this->_db = $dsn['database']; + } + + return DB_OK; + } + + // }}} + // {{{ disconnect() + + /** + * Disconnects from the database server + * + * @return bool TRUE on success, FALSE on failure + */ + function disconnect() + { + $ret = @sybase_close($this->connection); + $this->connection = null; + return $ret; + } + + // }}} + // {{{ simpleQuery() + + /** + * Sends a query to the database server + * + * @param string the SQL query string + * + * @return mixed + a PHP result resrouce for successful SELECT queries + * + the DB_OK constant for other successful queries + * + a DB_Error object on failure + */ + function simpleQuery($query) + { + $ismanip = $this->_checkManip($query); + $this->last_query = $query; + if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { + return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); + } + $query = $this->modifyQuery($query); + if (!$this->autocommit && $ismanip) { + if ($this->transaction_opcount == 0) { + $result = @sybase_query('BEGIN TRANSACTION', $this->connection); + if (!$result) { + return $this->sybaseRaiseError(); + } + } + $this->transaction_opcount++; + } + $result = @sybase_query($query, $this->connection); + if (!$result) { + return $this->sybaseRaiseError(); + } + if (is_resource($result)) { + return $result; + } + // Determine which queries that should return data, and which + // should return an error code only. + return $ismanip ? DB_OK : $result; + } + + // }}} + // {{{ nextResult() + + /** + * Move the internal sybase result pointer to the next available result + * + * @param a valid sybase result resource + * + * @access public + * + * @return true if a result is available otherwise return false + */ + function nextResult($result) + { + return false; + } + + // }}} + // {{{ fetchInto() + + /** + * Places a row from the result set into the given array + * + * Formating of the array and the data therein are configurable. + * See DB_result::fetchInto() for more information. + * + * This method is not meant to be called directly. Use + * DB_result::fetchInto() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result the query result resource + * @param array $arr the referenced array to put the data in + * @param int $fetchmode how the resulting array should be indexed + * @param int $rownum the row number to fetch (0 = first row) + * + * @return mixed DB_OK on success, NULL when the end of a result set is + * reached or on failure + * + * @see DB_result::fetchInto() + */ + function fetchInto($result, &$arr, $fetchmode, $rownum = null) + { + if ($rownum !== null) { + if (!@sybase_data_seek($result, $rownum)) { + return null; + } + } + if ($fetchmode & DB_FETCHMODE_ASSOC) { + if (function_exists('sybase_fetch_assoc')) { + $arr = @sybase_fetch_assoc($result); + } else { + if ($arr = @sybase_fetch_array($result)) { + foreach ($arr as $key => $value) { + if (is_int($key)) { + unset($arr[$key]); + } + } + } + } + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) { + $arr = array_change_key_case($arr, CASE_LOWER); + } + } else { + $arr = @sybase_fetch_row($result); + } + if (!$arr) { + return null; + } + if ($this->options['portability'] & DB_PORTABILITY_RTRIM) { + $this->_rtrimArrayValues($arr); + } + if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) { + $this->_convertNullArrayValuesToEmpty($arr); + } + return DB_OK; + } + + // }}} + // {{{ freeResult() + + /** + * Deletes the result set and frees the memory occupied by the result set + * + * This method is not meant to be called directly. Use + * DB_result::free() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return bool TRUE on success, FALSE if $result is invalid + * + * @see DB_result::free() + */ + function freeResult($result) + { + return is_resource($result) ? sybase_free_result($result) : false; + } + + // }}} + // {{{ numCols() + + /** + * Gets the number of columns in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numCols() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of columns. A DB_Error object on failure. + * + * @see DB_result::numCols() + */ + function numCols($result) + { + $cols = @sybase_num_fields($result); + if (!$cols) { + return $this->sybaseRaiseError(); + } + return $cols; + } + + // }}} + // {{{ numRows() + + /** + * Gets the number of rows in a result set + * + * This method is not meant to be called directly. Use + * DB_result::numRows() instead. It can't be declared "protected" + * because DB_result is a separate object. + * + * @param resource $result PHP's query result resource + * + * @return int the number of rows. A DB_Error object on failure. + * + * @see DB_result::numRows() + */ + function numRows($result) + { + $rows = @sybase_num_rows($result); + if ($rows === false) { + return $this->sybaseRaiseError(); + } + return $rows; + } + + // }}} + // {{{ affectedRows() + + /** + * Determines the number of rows affected by a data maniuplation query + * + * 0 is returned for queries that don't manipulate data. + * + * @return int the number of rows. A DB_Error object on failure. + */ + function affectedRows() + { + if ($this->_last_query_manip) { + $result = @sybase_affected_rows($this->connection); + } else { + $result = 0; + } + return $result; + } + + // }}} + // {{{ nextId() + + /** + * Returns the next free id in a sequence + * + * @param string $seq_name name of the sequence + * @param boolean $ondemand when true, the seqence is automatically + * created if it does not exist + * + * @return int the next id number in the sequence. + * A DB_Error object on failure. + * + * @see DB_common::nextID(), DB_common::getSequenceName(), + * DB_sybase::createSequence(), DB_sybase::dropSequence() + */ + function nextId($seq_name, $ondemand = true) + { + $seqname = $this->getSequenceName($seq_name); + if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { + return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); + } + $repeat = 0; + do { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)"); + $this->popErrorHandling(); + if ($ondemand && DB::isError($result) && + ($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE)) + { + $repeat = 1; + $result = $this->createSequence($seq_name); + if (DB::isError($result)) { + return $this->raiseError($result); + } + } elseif (!DB::isError($result)) { + $result = $this->query("SELECT @@IDENTITY FROM $seqname"); + $repeat = 0; + } else { + $repeat = false; + } + } while ($repeat); + if (DB::isError($result)) { + return $this->raiseError($result); + } + $result = $result->fetchRow(DB_FETCHMODE_ORDERED); + return $result[0]; + } + + /** + * Creates a new sequence + * + * @param string $seq_name name of the new sequence + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::createSequence(), DB_common::getSequenceName(), + * DB_sybase::nextID(), DB_sybase::dropSequence() + */ + function createSequence($seq_name) + { + return $this->query('CREATE TABLE ' + . $this->getSequenceName($seq_name) + . ' (id numeric(10, 0) IDENTITY NOT NULL,' + . ' vapor int NULL)'); + } + + // }}} + // {{{ dropSequence() + + /** + * Deletes a sequence + * + * @param string $seq_name name of the sequence to be deleted + * + * @return int DB_OK on success. A DB_Error object on failure. + * + * @see DB_common::dropSequence(), DB_common::getSequenceName(), + * DB_sybase::nextID(), DB_sybase::createSequence() + */ + function dropSequence($seq_name) + { + return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)); + } + + // }}} + // {{{ quoteFloat() + + /** + * Formats a float value for use within a query in a locale-independent + * manner. + * + * @param float the float value to be quoted. + * @return string the quoted string. + * @see DB_common::quoteSmart() + * @since Method available since release 1.7.8. + */ + function quoteFloat($float) { + return $this->escapeSimple(str_replace(',', '.', strval(floatval($float)))); + } + + // }}} + // {{{ autoCommit() + + /** + * Enables or disables automatic commits + * + * @param bool $onoff true turns it on, false turns it off + * + * @return int DB_OK on success. A DB_Error object if the driver + * doesn't support auto-committing transactions. + */ + function autoCommit($onoff = false) + { + // XXX if $this->transaction_opcount > 0, we should probably + // issue a warning here. + $this->autocommit = $onoff ? true : false; + return DB_OK; + } + + // }}} + // {{{ commit() + + /** + * Commits the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function commit() + { + if ($this->transaction_opcount > 0) { + if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { + return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); + } + $result = @sybase_query('COMMIT', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->sybaseRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ rollback() + + /** + * Reverts the current transaction + * + * @return int DB_OK on success. A DB_Error object on failure. + */ + function rollback() + { + if ($this->transaction_opcount > 0) { + if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { + return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); + } + $result = @sybase_query('ROLLBACK', $this->connection); + $this->transaction_opcount = 0; + if (!$result) { + return $this->sybaseRaiseError(); + } + } + return DB_OK; + } + + // }}} + // {{{ sybaseRaiseError() + + /** + * Produces a DB_Error object regarding the current problem + * + * @param int $errno if the error is being manually raised pass a + * DB_ERROR* constant here. If this isn't passed + * the error information gathered from the DBMS. + * + * @return object the DB_Error object + * + * @see DB_common::raiseError(), + * DB_sybase::errorNative(), DB_sybase::errorCode() + */ + function sybaseRaiseError($errno = null) + { + $native = $this->errorNative(); + if ($errno === null) { + $errno = $this->errorCode($native); + } + return $this->raiseError($errno, null, null, null, $native); + } + + // }}} + // {{{ errorNative() + + /** + * Gets the DBMS' native error message produced by the last query + * + * @return string the DBMS' error message + */ + function errorNative() + { + return @sybase_get_last_message(); + } + + // }}} + // {{{ errorCode() + + /** + * Determines PEAR::DB error code from the database's text error message. + * + * @param string $errormsg error message returned from the database + * @return integer an error number from a DB error constant + */ + function errorCode($errormsg) + { + static $error_regexps; + + // PHP 5.2+ prepends the function name to $php_errormsg, so we need + // this hack to work around it, per bug #9599. + $errormsg = preg_replace('/^sybase[a-z_]+\(\): /', '', $errormsg); + + if (!isset($error_regexps)) { + $error_regexps = array( + '/Incorrect syntax near/' + => DB_ERROR_SYNTAX, + '/^Unclosed quote before the character string [\"\'].*[\"\']\./' + => DB_ERROR_SYNTAX, + '/Implicit conversion (from datatype|of NUMERIC value)/i' + => DB_ERROR_INVALID_NUMBER, + '/Cannot drop the table [\"\'].+[\"\'], because it doesn\'t exist in the system catalogs\./' + => DB_ERROR_NOSUCHTABLE, + '/Only the owner of object [\"\'].+[\"\'] or a user with System Administrator \(SA\) role can run this command\./' + => DB_ERROR_ACCESS_VIOLATION, + '/^.+ permission denied on object .+, database .+, owner .+/' + => DB_ERROR_ACCESS_VIOLATION, + '/^.* permission denied, database .+, owner .+/' + => DB_ERROR_ACCESS_VIOLATION, + '/[^.*] not found\./' + => DB_ERROR_NOSUCHTABLE, + '/There is already an object named/' + => DB_ERROR_ALREADY_EXISTS, + '/Invalid column name/' + => DB_ERROR_NOSUCHFIELD, + '/does not allow null values/' + => DB_ERROR_CONSTRAINT_NOT_NULL, + '/Command has been aborted/' + => DB_ERROR_CONSTRAINT, + '/^Cannot drop the index .* because it doesn\'t exist/i' + => DB_ERROR_NOT_FOUND, + '/^There is already an index/i' + => DB_ERROR_ALREADY_EXISTS, + '/^There are fewer columns in the INSERT statement than values specified/i' + => DB_ERROR_VALUE_COUNT_ON_ROW, + '/Divide by zero/i' + => DB_ERROR_DIVZERO, + ); + } + + foreach ($error_regexps as $regexp => $code) { + if (preg_match($regexp, $errormsg)) { + return $code; + } + } + return DB_ERROR; + } + + // }}} + // {{{ tableInfo() + + /** + * Returns information about a table or a result set + * + * NOTE: only supports 'table' and 'flags' if $result + * is a table name. + * + * @param object|string $result DB_result object from a query or a + * string containing the name of a table. + * While this also accepts a query result + * resource identifier, this behavior is + * deprecated. + * @param int $mode a valid tableInfo mode + * + * @return array an associative array with the information requested. + * A DB_Error object on failure. + * + * @see DB_common::tableInfo() + * @since Method available since Release 1.6.0 + */ + function tableInfo($result, $mode = null) + { + if (is_string($result)) { + /* + * Probably received a table name. + * Create a result resource identifier. + */ + if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) { + return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED); + } + $id = @sybase_query("SELECT * FROM $result WHERE 1=0", + $this->connection); + $got_string = true; + } elseif (isset($result->result)) { + /* + * Probably received a result object. + * Extract the result resource identifier. + */ + $id = $result->result; + $got_string = false; + } else { + /* + * Probably received a result resource identifier. + * Copy it. + * Deprecated. Here for compatibility only. + */ + $id = $result; + $got_string = false; + } + + if (!is_resource($id)) { + return $this->sybaseRaiseError(DB_ERROR_NEED_MORE_DATA); + } + + if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) { + $case_func = 'strtolower'; + } else { + $case_func = 'strval'; + } + + $count = @sybase_num_fields($id); + $res = array(); + + if ($mode) { + $res['num_fields'] = $count; + } + + for ($i = 0; $i < $count; $i++) { + $f = @sybase_fetch_field($id, $i); + // column_source is often blank + $res[$i] = array( + 'table' => $got_string + ? $case_func($result) + : $case_func($f->column_source), + 'name' => $case_func($f->name), + 'type' => $f->type, + 'len' => $f->max_length, + 'flags' => '', + ); + if ($res[$i]['table']) { + $res[$i]['flags'] = $this->_sybase_field_flags( + $res[$i]['table'], $res[$i]['name']); + } + if ($mode & DB_TABLEINFO_ORDER) { + $res['order'][$res[$i]['name']] = $i; + } + if ($mode & DB_TABLEINFO_ORDERTABLE) { + $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i; + } + } + + // free the result only if we were called on a table + if ($got_string) { + @sybase_free_result($id); + } + return $res; + } + + // }}} + // {{{ _sybase_field_flags() + + /** + * Get the flags for a field + * + * Currently supports: + * + unique_key (unique index, unique check or primary_key) + * + multiple_key (multi-key index) + * + * @param string $table the table name + * @param string $column the field name + * + * @return string space delimited string of flags. Empty string if none. + * + * @access private + */ + function _sybase_field_flags($table, $column) + { + static $tableName = null; + static $flags = array(); + + if ($table != $tableName) { + $flags = array(); + $tableName = $table; + + /* We're running sp_helpindex directly because it doesn't exist in + * older versions of ASE -- unfortunately, we can't just use + * DB::isError() because the user may be using callback error + * handling. */ + $res = @sybase_query("sp_helpindex $table", $this->connection); + + if ($res === false || $res === true) { + // Fake a valid response for BC reasons. + return ''; + } + + while (($val = sybase_fetch_assoc($res)) !== false) { + if (!isset($val['index_keys'])) { + /* No useful information returned. Break and be done with + * it, which preserves the pre-1.7.9 behaviour. */ + break; + } + + $keys = explode(', ', trim($val['index_keys'])); + + if (sizeof($keys) > 1) { + foreach ($keys as $key) { + $this->_add_flag($flags[$key], 'multiple_key'); + } + } + + if (strpos($val['index_description'], 'unique')) { + foreach ($keys as $key) { + $this->_add_flag($flags[$key], 'unique_key'); + } + } + } + + sybase_free_result($res); + + } + + if (array_key_exists($column, $flags)) { + return(implode(' ', $flags[$column])); + } + + return ''; + } + + // }}} + // {{{ _add_flag() + + /** + * Adds a string to the flags array if the flag is not yet in there + * - if there is no flag present the array is created + * + * @param array $array reference of flags array to add a value to + * @param mixed $value value to add to the flag array + * + * @return void + * + * @access private + */ + function _add_flag(&$array, $value) + { + if (!is_array($array)) { + $array = array($value); + } elseif (!in_array($value, $array)) { + array_push($array, $value); + } + } + + // }}} + // {{{ getSpecialQuery() + + /** + * Obtains the query string needed for listing a given type of objects + * + * @param string $type the kind of objects you want to retrieve + * + * @return string the SQL query string or null if the driver doesn't + * support the object type requested + * + * @access protected + * @see DB_common::getListOf() + */ + function getSpecialQuery($type) + { + switch ($type) { + case 'tables': + return "SELECT name FROM sysobjects WHERE type = 'U'" + . ' ORDER BY name'; + case 'views': + return "SELECT name FROM sysobjects WHERE type = 'V'"; + default: + return null; + } + } + + // }}} + +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ + +?> diff --git a/common/PEAR/File.php b/common/PEAR/File.php new file mode 100644 index 0000000..2c755f6 --- /dev/null +++ b/common/PEAR/File.php @@ -0,0 +1,534 @@ + + * @author Tal Peer + * @author Michael Wallner + * @copyright 2002-2005 The Authors + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: File.php,v 1.31 2005/07/21 07:53:09 mike Exp $ + * @link http://pear.php.net/package/File + */ + +/** + * Requires PEAR + */ +require_once 'PEAR.php'; + +/** + * The default number of bytes for reading + */ +if (!defined('FILE_DEFAULT_READSIZE')) { + define('FILE_DEFAULT_READSIZE', 1024, true); +} + +/** + * The maximum number of bytes for reading lines + */ +if (!defined('FILE_MAX_LINE_READSIZE')) { + define('FILE_MAX_LINE_READSIZE', 40960, true); +} + +/** + * Whether file locks should block + */ +if (!defined('FILE_LOCKS_BLOCK')) { + define('FILE_LOCKS_BLOCK', true, true); +} + +/** + * Mode to use for reading from files + */ +define('FILE_MODE_READ', 'rb', true); + +/** + * Mode to use for truncating files, then writing + */ +define('FILE_MODE_WRITE', 'wb', true); + +/** + * Mode to use for appending to files + */ +define('FILE_MODE_APPEND', 'ab', true); + +/** + * Use this when a shared (read) lock is required + */ +define('FILE_LOCK_SHARED', LOCK_SH | (FILE_LOCKS_BLOCK ? 0 : LOCK_NB), true); + +/** + * Use this when an exclusive (write) lock is required + */ +define('FILE_LOCK_EXCLUSIVE', LOCK_EX | (FILE_LOCKS_BLOCK ? 0 : LOCK_NB), true); + +/** + * Class for handling files + * + * A class with common functions for writing, + * reading and handling files and directories + * + * @author Richard Heyes + * @author Tal Peer + * @author Michael Wallner + * @access public + * @package File + * + * @static + */ +class File extends PEAR +{ + /** + * Destructor + * + * Unlocks any locked file pointers and closes all filepointers + * + * @access private + */ + function _File() + { + File::closeAll(); + } + + /** + * Handles file pointers. If a file pointer needs to be opened, + * it will be. If it already exists (based on filename and mode) + * then the existing one will be returned. + * + * @access private + * @param string $filename Filename to be used + * @param string $mode Mode to open the file in + * @param mixed $lock Type of lock to use + * @return mixed PEAR_Error on error or file pointer resource on success + */ + function &_getFilePointer($filename, $mode, $lock = false) + { + $filePointers = &PEAR::getStaticProperty('File', 'filePointers'); + + // Win32 is case-insensitive + if (OS_WINDOWS) { + $filename = strToLower($filename); + } + + // check if file pointer already exists + if ( !isset($filePointers[$filename][$mode]) || + !is_resource($filePointers[$filename][$mode])) { + + // check if we can open the file in the desired mode + switch ($mode) + { + case FILE_MODE_READ: + if ( !preg_match('/^.+(? $modes) { + foreach (array_keys($modes) as $mode) { + if (is_resource($filePointers[$fname][$mode])) { + @fclose($filePointers[$fname][$mode]); + } + unset($filePointers[$fname][$mode]); + } + } + } + } + + /** + * This closes an open file pointer + * + * @access public + * @param string $filename The filename that was opened + * @param string $mode Mode the file was opened in + * @return mixed PEAR Error on error, true otherwise + */ + function close($filename, $mode) + { + $filePointers = &PEAR::getStaticProperty('File', 'filePointers'); + + if (OS_WINDOWS) { + $filename = strToLower($filename); + } + if (!isset($filePointers[$filename][$mode])) { + return true; + } + + $fp = $filePointers[$filename][$mode]; + unset($filePointers[$filename][$mode]); + + if (is_resource($fp)) { + // unlock file + @flock($fp, LOCK_UN); + // close file + if (!@fclose($fp)) { + return PEAR::raiseError("Cannot close file: $filename"); + } + } + + return true; + } + + /** + * This unlocks a locked file pointer. + * + * @access public + * @param string $filename The filename that was opened + * @param string $mode Mode the file was opened in + * @return mixed PEAR Error on error, true otherwise + */ + function unlock($filename, $mode) + { + if (PEAR::isError($fp = &File::_getFilePointer($filename, $mode))) { + return $fp; + } + if (!@flock($fp, LOCK_UN)) { + return PEAR::raiseError("Cacnnot unlock file: $filename"); + } + return true; + } + + /** + * @deprecated + */ + function stripTrailingSeparators($path, $separator = DIRECTORY_SEPARATOR) + { + return rtrim($path, $separator); + } + + /** + * @deprecated + */ + function stripLeadingSeparators($path, $separator = DIRECTORY_SEPARATOR) + { + return ltrim($path, $separator); + } + + /** + * @deprecated Use File_Util::buildPath() instead. + */ + function buildPath($parts, $separator = DIRECTORY_SEPARATOR) + { + require_once 'File/Util.php'; + return File_Util::buildPath($parts, $separator); + } + + /** + * @deprecated Use File_Util::skipRoot() instead. + */ + function skipRoot($path) + { + require_once 'File/Util.php'; + return File_Util::skipRoot($path); + } + + /** + * @deprecated Use File_Util::tmpDir() instead. + */ + function getTempDir() + { + require_once 'File/Util.php'; + return File_Util::tmpDir(); + } + + /** + * @deprecated Use File_Util::tmpFile() instead. + */ + function getTempFile($dirname = null) + { + require_once 'File/Util.php'; + return File_Util::tmpFile($dirname); + } + + /** + * @deprecated Use File_Util::isAbsolute() instead. + */ + function isAbsolute($path) + { + require_once 'File/Util.php'; + return File_Util::isAbsolute($path); + } + + /** + * @deprecated Use File_Util::relativePath() instead. + */ + function relativePath($path, $root, $separator = DIRECTORY_SEPARATOR) + { + require_once 'File/Util.php'; + return File_Util::relativePath($path, $root, $separator); + } + + /** + * @deprecated Use File_Util::realpath() instead. + */ + function realpath($path, $separator = DIRECTORY_SEPARATOR) + { + require_once 'File/Util.php'; + return File_Util::realpath($path, $separator); + } +} + +PEAR::registerShutdownFunc(array('File', '_File')); + +?> diff --git a/common/PEAR/File/CSV.php b/common/PEAR/File/CSV.php new file mode 100644 index 0000000..c4c4d44 --- /dev/null +++ b/common/PEAR/File/CSV.php @@ -0,0 +1,514 @@ + + * @author Helgi ormar + * @copyright 2004-2005 The Authors + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: CSV.php,v 1.24 2005/08/09 08:16:02 dufuz Exp $ + * @link http://pear.php.net/package/File + */ + +require_once 'PEAR.php'; +require_once 'File.php'; + +/** +* File class for handling CSV files (Comma Separated Values), a common format +* for exchanging data. +* +* TODO: +* - Usage example and Doc +* - Use getPointer() in discoverFormat +* - Add a line counter for being able to output better error reports +* - Store the last error in GLOBALS and add File_CSV::getLastError() +* +* Wish: +* - Other methods like readAll(), writeAll(), numFields(), numRows() +* - Try to detect if a CSV has header or not in discoverFormat() +* +* Known Bugs: +* (they has been analyzed but for the moment the impact in the speed for +* properly handle this uncommon cases is too high and won't be supported) +* - A field which is composed only by a single quoted separator (ie -> ;";";) +* is not handled properly +* - When there is exactly one field minus than the expected number and there +* is a field with a separator inside, the parser will throw the "wrong count" error +* +* @author Tomas V.V.Cox +* @author Helgi ormar +* @package File +*/ +class File_CSV +{ + /** + * This raiseError method works in a different way. It will always return + * false (an error occurred) but it will call PEAR::raiseError() before + * it. If no default PEAR global handler is set, will trigger an error. + * + * @param string $error The error message + * @return bool always false + */ + function raiseError($error) + { + // If a default PEAR Error handler is not set trigger the error + // XXX Add a PEAR::isSetHandler() method? + if ($GLOBALS['_PEAR_default_error_mode'] == PEAR_ERROR_RETURN) { + PEAR::raiseError($error, null, PEAR_ERROR_TRIGGER, E_USER_WARNING); + } else { + PEAR::raiseError($error); + } + return false; + } + + /** + * Checks the configuration given by the user + * + * @access private + * @param string &$error The error will be written here if any + * @param array &$conf The configuration assoc array + * @return string error Returns a error message + */ + function _conf(&$error, &$conf) + { + // check conf + if (!is_array($conf)) { + return $error = 'Invalid configuration'; + } + + if (!isset($conf['fields']) || !is_numeric($conf['fields'])) { + return $error = 'The number of fields must be numeric (the "fields" key)'; + } + + if (isset($conf['sep'])) { + if (strlen($conf['sep']) != 1) { + return $error = 'Separator can only be one char'; + } + } elseif ($conf['fields'] > 1) { + return $error = 'Missing separator (the "sep" key)'; + } + + if (isset($conf['quote'])) { + if (strlen($conf['quote']) != 1) { + return $error = 'The quote char must be one char (the "quote" key)'; + } + } else { + $conf['quote'] = null; + } + + if (!isset($conf['crlf'])) { + $conf['crlf'] = "\n"; + } + + if (!isset($conf['eol2unix'])) { + $conf['eol2unix'] = true; + } + } + + /** + * Return or create the file descriptor associated with a file + * + * @param string $file The name of the file + * @param array &$conf The configuration + * @param string $mode The open node (ex: FILE_MODE_READ or FILE_MODE_WRITE) + * @param boolean $reset if passed as true and resource for the file exists + * than the file pointer will be moved to the beginning + * + * @return mixed A file resource or false + */ + function getPointer($file, &$conf, $mode = FILE_MODE_READ, $reset = false) + { + static $resources = array(); + static $config; + if (isset($resources[$file])) { + $conf = $config; + if ($reset) { + fseek($resources[$file], 0); + } + return $resources[$file]; + } + File_CSV::_conf($error, $conf); + if ($error) { + return File_CSV::raiseError($error); + } + $config = $conf; + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $fp = &File::_getFilePointer($file, $mode); + PEAR::popErrorHandling(); + if (PEAR::isError($fp)) { + return File_CSV::raiseError($fp); + } + $resources[$file] = $fp; + + if ($mode == FILE_MODE_READ && !empty($conf['header'])) { + if (!File_CSV::read($file, $conf)) { + return false; + } + } + return $fp; + } + + /** + * Unquote data + * + * @param string $field The data to unquote + * @param string $quote The quote char + * @return string the unquoted data + */ + function unquote($field, $quote) + { + // Trim first the string. + $field = trim($field); + $quote = trim($quote); + + // Incase null fields (form: ;;) + if (!strlen($field)) { + return $field; + } + + if ($quote && $field{0} == $quote && $field{strlen($field)-1} == $quote) { + return substr($field, 1, -1); + } + return $field; + } + + /** + * Reads a row of data as an array from a CSV file. It's able to + * read memo fields with multiline data. + * + * @param string $file The filename where to write the data + * @param array &$conf The configuration of the dest CSV + * + * @return mixed Array with the data read or false on error/no more data + */ + function readQuoted($file, &$conf) + { + if (!$fp = File_CSV::getPointer($file, $conf, FILE_MODE_READ)) { + return false; + } + + $buff = $c = ''; + $ret = array(); + $i = 1; + $in_quote = false; + $quote = $conf['quote']; + $f = $conf['fields']; + $eol2unix = $conf['eol2unix']; + while (($ch = fgetc($fp)) !== false) { + $prev = $c; + $c = $ch; + // Common case + if ($c != $quote && $c != $conf['sep'] && $c != "\n" && $c != "\r") { + $buff .= $c; + continue; + } + + // Start quote. + if ($quote && $c == $quote && + ($prev == $conf['sep'] || $prev == "\n" || $prev === null || + $prev == "\r" || $prev == '')) + { + $in_quote = true; + } + + if ($in_quote) { + // When ends quote + if ($c == $conf['sep'] && $prev == $conf['quote']) { + $in_quote = false; + } elseif ($c == "\n" || $c == "\r") { + $sub = ($prev == "\r") ? 2 : 1; + if ((strlen($buff) >= $sub) && + ($buff{strlen($buff) - $sub} == $quote)) + { + $in_quote = false; + } + } + } + + if (!$in_quote && ($c == $conf['sep'] || $c == "\n" || $c == "\r") && $prev != '') { + // More fields than expected + if (($c == $conf['sep']) && ((count($ret) + 1) == $f)) { + // Seek the pointer into linebreak character. + while (true) { + $c = fgetc($fp); + if ($c == "\n" || $c == "\r") { + break; + } + } + + // Insert last field value. + $ret[] = File_CSV::unquote($buff, $quote); + return $ret; + } + + // Less fields than expected + if (($c == "\n" || $c == "\r") && ($i != $f)) { + // Insert last field value. + $ret[] = File_CSV::unquote($buff, $quote); + + // Pair the array elements to fields count. + return array_merge($ret, + array_fill(count($ret), + ($f - 1) - (count($ret) - 1), + '') + ); + } + + if ($prev == "\r") { + $buff = substr($buff, 0, -1); + } + + // Convert EOL character to Unix EOL (LF). + if ($eol2unix) { + $buff = preg_replace('/(\r\n|\r)$/', "\n", $buff); + } + + $ret[] = File_CSV::unquote($buff, $quote); + if (count($ret) == $f) { + return $ret; + } + $buff = ''; + $i++; + continue; + } + $buff .= $c; + } + return !feof($fp) ? $ret : false; + } + + /** + * Reads a "row" from a CSV file and return it as an array + * + * @param string $file The CSV file + * @param array &$conf The configuration of the dest CSV + * + * @return mixed Array or false + */ + function read($file, &$conf) + { + if (!$fp = File_CSV::getPointer($file, $conf, FILE_MODE_READ)) { + return false; + } + // The size is limited to 4K + if (!$line = fgets($fp, 4096)) { + return false; + } + + $fields = $conf['fields'] == 1 ? array($line) : explode($conf['sep'], $line); + + if ($conf['quote']) { + $last =& $fields[count($fields) - 1]; + // Fallback to read the line with readQuoted when guess + // that the simple explode won't work right + if (($last{strlen($last) - 1} == "\n" + && $last{0} == $conf['quote'] + && $last{strlen(rtrim($last)) - 1} != $conf['quote']) + || + (count($fields) != $conf['fields']) + // XXX perhaps there is a separator inside a quoted field + //preg_match("|{$conf['quote']}.*{$conf['sep']}.*{$conf['quote']}|U", $line) + ) + { + fseek($fp, -1 * strlen($line), SEEK_CUR); + return File_CSV::readQuoted($file, $conf); + } else { + $last = rtrim($last); + foreach ($fields as $k => $v) { + $fields[$k] = File_CSV::unquote($v, $conf['quote']); + } + } + } + + if (count($fields) != $conf['fields']) { + File_CSV::raiseError("Read wrong fields number count: '". count($fields) . + "' expected ".$conf['fields']); + return true; + } + return $fields; + } + + /** + * Internal use only, will be removed in the future + * + * @param string $str The string to debug + * @access private + */ + function _dbgBuff($str) + { + if (strpos($str, "\r") !== false) { + $str = str_replace("\r", "_r_", $str); + } + if (strpos($str, "\n") !== false) { + $str = str_replace("\n", "_n_", $str); + } + if (strpos($str, "\t") !== false) { + $str = str_replace("\t", "_t_", $str); + } + echo "buff: ($str)\n"; + } + + /** + * Writes a struc (array) in a file as CSV + * + * @param string $file The filename where to write the data + * @param array $fields Ordered array with the data + * @param array &$conf The configuration of the dest CSV + * + * @return bool True on success false otherwise + */ + function write($file, $fields, &$conf) + { + if (!$fp = File_CSV::getPointer($file, $conf, FILE_MODE_WRITE)) { + return false; + } + if (count($fields) != $conf['fields']) { + File_CSV::raiseError("Wrong fields number count: '". count($fields) . + "' expected ".$conf['fields']); + return true; + } + $write = ''; + for ($i = 0; $i < count($fields); $i++) { + if (!is_numeric($fields[$i]) && $conf['quote']) { + $write .= $conf['quote'] . $fields[$i] . $conf['quote']; + } else { + $write .= $fields[$i]; + } + if ($i < (count($fields) - 1)) { + $write .= $conf['sep']; + } else { + $write .= $conf['crlf']; + } + } + if (!fwrite($fp, $write)) { + return File_CSV::raiseError('Can not write to file'); + } + return true; + } + + /** + * Discover the format of a CSV file (the number of fields, the separator + * and if it quote string fields) + * + * @param string the CSV file name + * @param array extra separators that should be checked for. + * @return mixed Assoc array or false + */ + function discoverFormat($file, $extraSeps = array()) + { + if (!$fp = @fopen($file, 'r')) { + return File_CSV::raiseError("Could not open file: $file"); + } + $seps = array("\t", ';', ':', ','); + $seps = array_merge($seps, $extraSeps); + $matches = array(); + + // Set auto detect line ending for Mac EOL support if < PHP 4.3.0. + $phpver = version_compare('4.3.0', phpversion(), '<'); + if ($phpver) { + $oldini = ini_get('auto_detect_line_endings'); + ini_set('auto_detect_line_endings', '1'); + } + + // Take the first 10 lines and store the number of ocurrences + // for each separator in each line + + $lines = file($file); + if (count($lines) > 10) { + $lines = array_slice($lines, 0, 10); + } + + if ($phpver) { + ini_set('auto_detect_line_endings', $oldini); + } + + foreach ($lines as $line) { + foreach ($seps as $sep) { + $matches[$sep][] = substr_count($line, $sep); + } + } + + $final = array(); + // Group the results by amount of equal ocurrences + foreach ($matches as $sep => $res) { + $times = array(); + $times[0] = 0; + foreach ($res as $k => $num) { + if ($num > 0) { + $times[$num] = (isset($times[$num])) ? $times[$num] + 1 : 1; + } + } + arsort($times); + + // Use max fields count. + $fields[$sep] = max(array_flip($times)); + $amount[$sep] = $times[key($times)]; + } + + arsort($amount); + $sep = key($amount); + + $conf['fields'] = $fields[$sep] + 1; + $conf['sep'] = $sep; + + // Test if there are fields with quotes arround in the first 5 lines + $quotes = '"\''; + $quote = null; + if (count($lines) > 5) { + $lines = array_slice($lines, 0, 5); + } + + foreach ($lines as $line) { + if (preg_match("|$sep([$quotes]).*([$quotes])$sep|U", $line, $match)) { + if ($match[1] == $match[2]) { + $quote = $match[1]; + break; + } + } + if (preg_match("|^([$quotes]).*([$quotes])$sep{0,1}|", $line, $match) + || preg_match("|([$quotes]).*([$quotes])$sep\s$|Us", $line, $match)) + { + if ($match[1] == $match[2]) { + $quote = $match[1]; + break; + } + } + } + $conf['quote'] = $quote; + fclose($fp); + // XXX What about trying to discover the "header"? + return $conf; + } + + /** + * Front to call getPointer and moving the resource to the + * beginning of the file + * Reset it if you like. + * + * @param string $file The name of the file + * @param array &$conf The configuration + * @param string $mode The open node (ex: FILE_MODE_READ or FILE_MODE_WRITE) + * + * @return boolean true on success false on failure + */ + function resetPointer($file, &$conf, $mode) + { + if (!File_CSV::getPointer($file, $conf, $mode, true)) { + return false; + } + + return true; + } +} +?> \ No newline at end of file diff --git a/common/PEAR/File/Util.php b/common/PEAR/File/Util.php new file mode 100644 index 0000000..941c614 --- /dev/null +++ b/common/PEAR/File/Util.php @@ -0,0 +1,457 @@ + + * @copyright 2004-2005 Michael Wallner + * @license http://www.php.net/license/3_0.txt PHP License 3.0 + * @version CVS: $Id: Util.php,v 1.21 2005/08/09 07:52:13 mike Exp $ + * @link http://pear.php.net/package/File + */ + +/**#@+ + * Sorting Constants + */ +define('FILE_SORT_NONE', 0); +define('FILE_SORT_REVERSE', 1); +define('FILE_SORT_NAME', 2); +define('FILE_SORT_SIZE', 4); +define('FILE_SORT_DATE', 8); +define('FILE_SORT_RANDOM', 16); +/**#@-*/ + +/**#@+ + * Listing Constants + */ +define('FILE_LIST_FILES', 1); +define('FILE_LIST_DIRS', 2); +define('FILE_LIST_DOTS', 4); +define('FILE_LIST_ALL', FILE_LIST_FILES | FILE_LIST_DIRS | FILE_LIST_DOTS); +/**#@-*/ + +/** + * @ignore + */ +define('FILE_WIN32', defined('OS_WINDOWS') ? OS_WINDOWS : !strncasecmp(PHP_OS, 'win', 3)); + +/** + * File_Util + * + * File and directory utility functions. + * + * @access public + * @static + */ +class File_Util +{ + /** + * Returns a string path built from the array $pathParts. Where a join + * occurs multiple separators are removed. Joins using the optional + * separator, defaulting to the PHP DIRECTORY_SEPARATOR constant. + * + * @static + * @access public + * @param array $parts Array containing the parts to be joined + * @param string $separator The directory seperator + */ + function buildPath($parts, $separator = DIRECTORY_SEPARATOR) + { + $qs = '/^'. preg_quote($separator, '/') .'+$/'; + for ($i = 0, $c = count($parts); $i < $c; $i++) { + if (!strlen($parts[$i]) || preg_match($qs, $parts[$i])) { + unset($parts[$i]); + } elseif (0 == $i) { + $parts[$i] = rtrim($parts[$i], $separator); + } elseif ($c - 1 == $i) { + $parts[$i] = ltrim($parts[$i], $separator); + } else { + $parts[$i] = trim($parts[$i], $separator); + } + } + return implode($separator, $parts); + } + + /** + * Returns a path without leading / or C:\. If this is not + * present the path is returned as is. + * + * @static + * @access public + * @param string $path The path to be processed + * @return string The processed path or the path as is + */ + function skipRoot($path) + { + if (File_Util::isAbsolute($path)) { + if (FILE_WIN32) { + return substr($path, $path{3} == '\\' ? 4 : 3); + } + return ltrim($path, '/'); + } + return $path; + } + + /** + * Returns the temp directory according to either the TMP, TMPDIR, or + * TEMP env variables. If these are not set it will also check for the + * existence of /tmp, %WINDIR%\temp + * + * @static + * @access public + * @return string The system tmp directory + */ + function tmpDir() + { + if (FILE_WIN32) { + if (isset($_ENV['TEMP'])) { + return $_ENV['TEMP']; + } + if (isset($_ENV['TMP'])) { + return $_ENV['TMP']; + } + if (isset($_ENV['windir'])) { + return $_ENV['windir'] . '\\temp'; + } + if (isset($_ENV['SystemRoot'])) { + return $_ENV['SystemRoot'] . '\\temp'; + } + if (isset($_SERVER['TEMP'])) { + return $_SERVER['TEMP']; + } + if (isset($_SERVER['TMP'])) { + return $_SERVER['TMP']; + } + if (isset($_SERVER['windir'])) { + return $_SERVER['windir'] . '\\temp'; + } + if (isset($_SERVER['SystemRoot'])) { + return $_SERVER['SystemRoot'] . '\\temp'; + } + return '\temp'; + } + if (isset($_ENV['TMPDIR'])) { + return $_ENV['TMPDIR']; + } + if (isset($_SERVER['TMPDIR'])) { + return $_SERVER['TMPDIR']; + } + return '/tmp'; + } + + /** + * Returns a temporary filename using tempnam() and File::tmpDir(). + * + * @static + * @access public + * @param string $dirname Optional directory name for the tmp file + * @return string Filename and path of the tmp file + */ + function tmpFile($dirname = null) + { + if (!isset($dirname)) { + $dirname = File_Util::tmpDir(); + } + return tempnam($dirname, 'temp.'); + } + + /** + * Returns boolean based on whether given path is absolute or not. + * + * @static + * @access public + * @param string $path Given path + * @return boolean True if the path is absolute, false if it is not + */ + function isAbsolute($path) + { + if (preg_match('/(?:\/|\\\)\.\.(?=\/|$)/', $path)) { + return false; + } + if (FILE_WIN32) { + return preg_match('/^[a-zA-Z]:(\\\|\/)/', $path); + } + return ($path{0} == '/') || ($path{0} == '~'); + } + + /** + * Get path relative to another path + * + * @static + * @access public + * @return string + * @param string $path + * @param string $root + * @param string $separator + */ + function relativePath($path, $root, $separator = DIRECTORY_SEPARATOR) + { + $path = File_Util::realpath($path, $separator); + $root = File_Util::realpath($root, $separator); + $dirs = explode($separator, $path); + $comp = explode($separator, $root); + + if (FILE_WIN32) { + if (strcasecmp($dirs[0], $comp[0])) { + return $path; + } + unset($dirs[0], $comp[0]); + } + + foreach ($comp as $i => $part) { + if (isset($dirs[$i]) && $part == $dirs[$i]) { + unset($dirs[$i], $comp[$i]); + } else { + break; + } + } + + return str_repeat('..' . $separator, count($comp)) . implode($separator, $dirs); + } + + /** + * Get real path (works with non-existant paths) + * + * @static + * @access public + * @return string + * @param string $path + * @param string $separator + */ + function realPath($path, $separator = DIRECTORY_SEPARATOR) + { + if (!strlen($path)) { + return $separator; + } + + $drive = ''; + if (FILE_WIN32) { + $path = preg_replace('/[\\\\\/]/', $separator, $path); + if (preg_match('/([a-zA-Z]\:)(.*)/', $path, $matches)) { + $drive = $matches[1]; + $path = $matches[2]; + } else { + $cwd = getcwd(); + $drive = substr($cwd, 0, 2); + if ($path{0} !== $separator{0}) { + $path = substr($cwd, 3) . $separator . $path; + } + } + } elseif ($path{0} !== $separator) { + $path = getcwd() . $separator . $path; + } + + $dirStack = array(); + foreach (explode($separator, $path) as $dir) { + if (strlen($dir) && $dir !== '.') { + if ($dir == '..') { + array_pop($dirStack); + } else { + $dirStack[] = $dir; + } + } + } + + return $drive . $separator . implode($separator, $dirStack); + } + + /** + * Check whether path is in root path + * + * @static + * @access public + * @return bool + * @param string $path + * @param string $root + */ + function pathInRoot($path, $root) + { + static $realPaths = array(); + + if (!isset($realPaths[$root])) { + $realPaths[$root] = File_Util::realPath($root); + } + + return false !== strstr(File_Util::realPath($path), $realPaths[$root]); + } + + /** + * List Directory + * + * The final argument, $cb, is a callback that either evaluates to true or + * false and performs a filter operation, or it can also modify the + * directory/file names returned. To achieve the latter effect use as + * follows: + * + * + * name, "\n"; + * } + * ?> + * + * + * @static + * @access public + * @return array + * @param string $path + * @param int $list + * @param int $sort + * @param mixed $cb + */ + function listDir($path, $list = FILE_LIST_ALL, $sort = FILE_SORT_NONE, $cb = null) + { + if (!strlen($path) || !is_dir($path)) { + return null; + } + + $entries = array(); + for ($dir = dir($path); false !== $entry = $dir->read(); ) { + if ($list & FILE_LIST_DOTS || $entry{0} !== '.') { + $isRef = ($entry === '.' || $entry === '..'); + $isDir = $isRef || is_dir($path .'/'. $entry); + if ( ((!$isDir && $list & FILE_LIST_FILES) || + ($isDir && $list & FILE_LIST_DIRS)) && + (!is_callable($cb) || + call_user_func_array($cb, array(&$entry)))) { + $entries[] = (object) array( + 'name' => $entry, + 'size' => $isDir ? null : filesize($path .'/'. $entry), + 'date' => filemtime($path .'/'. $entry), + ); + } + } + } + $dir->close(); + + if ($sort) { + $entries = File_Util::sortFiles($entries, $sort); + } + + return $entries; + } + + /** + * Sort Files + * + * @static + * @access public + * @return array + * @param array $files + * @param int $sort + */ + function sortFiles($files, $sort) + { + if (!$files) { + return array(); + } + + if (!$sort) { + return $files; + } + + if ($sort === 1) { + return array_reverse($files); + } + + if ($sort & FILE_SORT_RANDOM) { + shuffle($files); + return $files; + } + + $names = array(); + $sizes = array(); + $dates = array(); + + if ($sort & FILE_SORT_NAME) { + $r = &$names; + } elseif ($sort & FILE_SORT_DATE) { + $r = &$dates; + } elseif ($sort & FILE_SORT_SIZE) { + $r = &$sizes; + } else { + asort($files, SORT_REGULAR); + return $files; + } + + $sortFlags = array( + FILE_SORT_NAME => SORT_STRING, + FILE_SORT_DATE => SORT_NUMERIC, + FILE_SORT_SIZE => SORT_NUMERIC, + ); + + foreach ($files as $file) { + $names[] = $file->name; + $sizes[] = $file->size; + $dates[] = $file->date; + } + + if ($sort & FILE_SORT_REVERSE) { + arsort($r, $sortFlags[$sort & ~1]); + } else { + asort($r, $sortFlags[$sort]); + } + + $result = array(); + foreach ($r as $i => $f) { + $result[] = $files[$i]; + } + + return $result; + } + + /** + * Switch File Extension + * + * @static + * @access public + * @return string|array + * @param string|array $filename + * @param string $to new file extension + * @param string $from change only files with this extension + * @param bool $reverse change only files not having $from extension + */ + function switchExt($filename, $to, $from = null, $reverse = false) + { + if (is_array($filename)) { + foreach ($filename as $key => $file) { + $filename[$key] = File_Util::switchExt($file, $to, $from); + } + return $filename; + } + + if ($len = strlen($from)) { + $ext = substr($filename, -$len - 1); + $cfn = FILE_WIN32 ? 'strcasecmp' : 'strcmp'; + if (!$reverse == $cfn($ext, '.'. $from)) { + return $filename; + } + return substr($filename, 0, -$len - 1) .'.'. $to; + } + + if ($pos = strpos($filename, '.')) { + return substr($filename, 0, $pos) .'.'. $to; + } + + return $filename .'.'. $to; + } + +} + +?> diff --git a/common/PEAR/HTML/Common.php b/common/PEAR/HTML/Common.php new file mode 100644 index 0000000..6e9d246 --- /dev/null +++ b/common/PEAR/HTML/Common.php @@ -0,0 +1,428 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.10 2005/09/01 10:28:57 thesaur Exp $ + +/** + * Base class for all HTML classes + * + * @author Adam Daniel + * @category HTML + * @package HTML_Common + * @version 1.2.2 + * @abstract + */ + +/** + * Base class for all HTML classes + * + * @author Adam Daniel + * @version 1.7 + * @since PHP 4.0.3pl1 + * @abstract + */ +class HTML_Common { + + /** + * Associative array of table attributes + * @var array + * @access private + */ + var $_attributes = array(); + + /** + * Tab offset of the table + * @var int + * @access private + */ + var $_tabOffset = 0; + + /** + * Tab string + * @var string + * @since 1.7 + * @access private + */ + var $_tab = "\11"; + + /** + * Contains the line end string + * @var string + * @since 1.7 + * @access private + */ + var $_lineEnd = "\12"; + + /** + * HTML comment on the object + * @var string + * @since 1.5 + * @access private + */ + var $_comment = ''; + + /** + * Class constructor + * @param mixed $attributes Associative array of table tag attributes + * or HTML attributes name="value" pairs + * @param int $tabOffset Indent offset in tabs + * @access public + */ + function HTML_Common($attributes = null, $tabOffset = 0) + { + $this->setAttributes($attributes); + $this->setTabOffset($tabOffset); + } // end constructor + + /** + * Returns the current API version + * @access public + * @returns double + */ + function apiVersion() + { + return 1.7; + } // end func apiVersion + + /** + * Returns the lineEnd + * + * @since 1.7 + * @access private + * @return string + * @throws + */ + function _getLineEnd() + { + return $this->_lineEnd; + } // end func getLineEnd + + /** + * Returns a string containing the unit for indenting HTML + * + * @since 1.7 + * @access private + * @return string + */ + function _getTab() + { + return $this->_tab; + } // end func _getTab + + /** + * Returns a string containing the offset for the whole HTML code + * + * @return string + * @access private + */ + function _getTabs() + { + return str_repeat($this->_getTab(), $this->_tabOffset); + } // end func _getTabs + + /** + * Returns an HTML formatted attribute string + * @param array $attributes + * @return string + * @access private + */ + function _getAttrString($attributes) + { + $strAttr = ''; + + if (is_array($attributes)) { + foreach ($attributes as $key => $value) { + $strAttr .= ' ' . $key . '="' . htmlspecialchars($value) . '"'; + } + } + return $strAttr; + } // end func _getAttrString + + /** + * Returns a valid atrributes array from either a string or array + * @param mixed $attributes Either a typical HTML attribute string or an associative array + * @access private + */ + function _parseAttributes($attributes) + { + if (is_array($attributes)) { + $ret = array(); + foreach ($attributes as $key => $value) { + if (is_int($key)) { + $key = $value = strtolower($value); + } else { + $key = strtolower($key); + } + $ret[$key] = $value; + } + return $ret; + + } elseif (is_string($attributes)) { + $preg = "/(([A-Za-z_:]|[^\\x00-\\x7F])([A-Za-z0-9_:.-]|[^\\x00-\\x7F])*)" . + "([ \\n\\t\\r]+)?(=([ \\n\\t\\r]+)?(\"[^\"]*\"|'[^']*'|[^ \\n\\t\\r]*))?/"; + if (preg_match_all($preg, $attributes, $regs)) { + for ($counter=0; $counter $value) { + $attr1[$key] = $value; + } + } // end func _updateAtrrArray + + /** + * Removes the given attribute from the given array + * + * @param string $attr Attribute name + * @param array $attributes Attribute array + * @since 1.4 + * @access private + * @return void + * @throws + */ + function _removeAttr($attr, &$attributes) + { + $attr = strtolower($attr); + if (isset($attributes[$attr])) { + unset($attributes[$attr]); + } + } //end func _removeAttr + + /** + * Returns the value of the given attribute + * + * @param string $attr Attribute name + * @since 1.5 + * @access public + * @return void + * @throws + */ + function getAttribute($attr) + { + $attr = strtolower($attr); + if (isset($this->_attributes[$attr])) { + return $this->_attributes[$attr]; + } + return null; + } //end func getAttribute + + /** + * Sets the HTML attributes + * @param mixed $attributes Either a typical HTML attribute string or an associative array + * @access public + */ + function setAttributes($attributes) + { + $this->_attributes = $this->_parseAttributes($attributes); + } // end func setAttributes + + /** + * Returns the assoc array (default) or string of attributes + * + * @param bool Whether to return the attributes as string + * @since 1.6 + * @access public + * @return mixed attributes + */ + function getAttributes($asString = false) + { + if ($asString) { + return $this->_getAttrString($this->_attributes); + } else { + return $this->_attributes; + } + } //end func getAttributes + + /** + * Updates the passed attributes without changing the other existing attributes + * @param mixed $attributes Either a typical HTML attribute string or an associative array + * @access public + */ + function updateAttributes($attributes) + { + $this->_updateAttrArray($this->_attributes, $this->_parseAttributes($attributes)); + } // end func updateAttributes + + /** + * Removes an attribute + * + * @param string $attr Attribute name + * @since 1.4 + * @access public + * @return void + * @throws + */ + function removeAttribute($attr) + { + $this->_removeAttr($attr, $this->_attributes); + } //end func removeAttribute + + /** + * Sets the line end style to Windows, Mac, Unix or a custom string. + * + * @param string $style "win", "mac", "unix" or custom string. + * @since 1.7 + * @access public + * @return void + */ + function setLineEnd($style) + { + switch ($style) { + case 'win': + $this->_lineEnd = "\15\12"; + break; + case 'unix': + $this->_lineEnd = "\12"; + break; + case 'mac': + $this->_lineEnd = "\15"; + break; + default: + $this->_lineEnd = $style; + } + } // end func setLineEnd + + /** + * Sets the tab offset + * + * @param int $offset + * @access public + */ + function setTabOffset($offset) + { + $this->_tabOffset = $offset; + } // end func setTabOffset + + /** + * Returns the tabOffset + * + * @since 1.5 + * @access public + * @return int + */ + function getTabOffset() + { + return $this->_tabOffset; + } //end func getTabOffset + + /** + * Sets the string used to indent HTML + * + * @since 1.7 + * @param string $string String used to indent ("\11", "\t", ' ', etc.). + * @access public + * @return void + */ + function setTab($string) + { + $this->_tab = $string; + } // end func setTab + + /** + * Sets the HTML comment to be displayed at the beginning of the HTML string + * + * @param string + * @since 1.4 + * @access public + * @return void + */ + function setComment($comment) + { + $this->_comment = $comment; + } // end func setHtmlComment + + /** + * Returns the HTML comment + * + * @since 1.5 + * @access public + * @return string + */ + function getComment() + { + return $this->_comment; + } //end func getComment + + /** + * Abstract method. Must be extended to return the objects HTML + * + * @access public + * @return string + * @abstract + */ + function toHtml() + { + return ''; + } // end func toHtml + + /** + * Displays the HTML to the screen + * + * @access public + */ + function display() + { + print $this->toHtml(); + } // end func display + +} // end class HTML_Common +?> diff --git a/common/PEAR/HTTP.php b/common/PEAR/HTTP.php new file mode 100644 index 0000000..8031c77 --- /dev/null +++ b/common/PEAR/HTTP.php @@ -0,0 +1,359 @@ + + * @author Sterling Hughes + * @author Tomas V.V.Cox + * @author Richard Heyes + * @author Philippe Jausions + * @author Michael Wallner + * @copyright 2002-2005 The Authors + * @license BSD, revised + * @version CVS: $Id: HTTP.php,v 1.48 2005/11/08 20:11:54 mike Exp $ + * @link http://pear.php.net/package/HTTP + */ + +/** + * Miscellaneous HTTP Utilities + * + * PEAR::HTTP provides static shorthand methods for generating HTTP dates, + * issueing HTTP HEAD requests, building absolute URIs, firing redirects and + * negotiating user preferred language. + * + * @package HTTP + * @category HTTP + * @access public + * @static + * @version $Revision: 1.48 $ + */ +class HTTP +{ + /** + * Date + * + * Format a RFC compliant GMT date HTTP header. This function honors the + * "y2k_compliance" php.ini directive and formats the GMT date corresponding + * to either RFC850 or RFC822. + * + * @static + * @access public + * @return mixed GMT date string, or false for an invalid $time parameter + * @param mixed $time unix timestamp or date (default = current time) + */ + function Date($time = null) + { + if (!isset($time)) { + $time = time(); + } elseif (!is_numeric($time) && (-1 === $time = strtotime($time))) { + return false; + } + + // RFC822 or RFC850 + $format = ini_get('y2k_compliance') ? 'D, d M Y' : 'l, d-M-y'; + + return gmdate($format .' H:i:s \G\M\T', $time); + } + + /** + * Negotiate Language + * + * Negotiate language with the user's browser through the Accept-Language + * HTTP header or the user's host address. Language codes are generally in + * the form "ll" for a language spoken in only one country, or "ll-CC" for a + * language spoken in a particular country. For example, U.S. English is + * "en-US", while British English is "en-UK". Portugese as spoken in + * Portugal is "pt-PT", while Brazilian Portugese is "pt-BR". + * + * Quality factors in the Accept-Language: header are supported, e.g.: + * Accept-Language: en-UK;q=0.7, en-US;q=0.6, no, dk;q=0.8 + * + * + * require_once 'HTTP.php'; + * $langs = array( + * 'en' => 'locales/en', + * 'en-US'=> 'locales/en', + * 'en-UK'=> 'locales/en', + * 'de' => 'locales/de', + * 'de-DE'=> 'locales/de', + * 'de-AT'=> 'locales/de', + * ); + * $neg = HTTP::negotiateLanguage($langs); + * $dir = $langs[$neg]; + * + * + * @static + * @access public + * @return string The negotiated language result or the supplied default. + * @param array $supported An associative array of supported languages, + * whose values must evaluate to true. + * @param string $default The default language to use if none is found. + */ + function negotiateLanguage($supported, $default = 'en-US') + { + $supp = array(); + foreach ($supported as $lang => $isSupported) { + if ($isSupported) { + $supp[strToLower($lang)] = $lang; + } + } + + if (!count($supp)) { + return $default; + } + + $matches = array(); + if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) { + foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $lang) { + $lang = array_map('trim', explode(';', $lang)); + if (isset($lang[1])) { + $l = strtolower($lang[0]); + $q = (float) str_replace('q=', '', $lang[1]); + } else { + $l = strtolower($lang[0]); + $q = null; + } + if (isset($supp[$l])) { + $matches[$l] = isset($q) ? $q : 1000 - count($matches); + } + } + } + + if (count($matches)) { + asort($matches, SORT_NUMERIC); + return $supp[end($l = array_keys($matches))]; + } + + if (isset($_SERVER['REMOTE_HOST'])) { + $lang = strtolower(end($h = explode('.', $_SERVER['REMOTE_HOST']))); + if (isset($supp[$lang])) { + return $supp[$lang]; + } + } + + return $default; + } + + /** + * Head + * + * Sends a "HEAD" HTTP command to a server and returns the headers + * as an associative array. Example output could be: + * + * Array + * ( + * [response_code] => 200 // The HTTP response code + * [response] => HTTP/1.1 200 OK // The full HTTP response string + * [Date] => Fri, 11 Jan 2002 01:41:44 GMT + * [Server] => Apache/1.3.20 (Unix) PHP/4.1.1 + * [X-Powered-By] => PHP/4.1.1 + * [Connection] => close + * [Content-Type] => text/html + * ) + * + * + * @see HTTP_Client::head() + * @see HTTP_Request + * + * @static + * @access public + * @return mixed Returns associative array of response headers on success + * or PEAR error on failure. + * @param string $url A valid URL, e.g.: http://pear.php.net/credits.php + * @param integer $timeout Timeout in seconds (default = 10) + */ + function head($url, $timeout = 10) + { + $p = parse_url($url); + if (!isset($p['scheme'])) { + $p = parse_url(HTTP::absoluteURI($url)); + } elseif ($p['scheme'] != 'http') { + return HTTP::raiseError('Unsupported protocol: '. $p['scheme']); + } + + $port = isset($p['port']) ? $p['port'] : 80; + + if (!$fp = @fsockopen($p['host'], $port, $eno, $estr, $timeout)) { + return HTTP::raiseError("Connection error: $estr ($eno)"); + } + + $path = !empty($p['path']) ? $p['path'] : '/'; + $path .= !empty($p['query']) ? '?' . $p['query'] : ''; + + fputs($fp, "HEAD $path HTTP/1.0\r\n"); + fputs($fp, 'Host: ' . $p['host'] . ':' . $port . "\r\n"); + fputs($fp, "Connection: close\r\n\r\n"); + + $response = rtrim(fgets($fp, 4096)); + if (preg_match("|^HTTP/[^\s]*\s(.*?)\s|", $response, $status)) { + $headers['response_code'] = $status[1]; + } + $headers['response'] = $response; + + while ($line = fgets($fp, 4096)) { + if (!trim($line)) { + break; + } + if (($pos = strpos($line, ':')) !== false) { + $header = substr($line, 0, $pos); + $value = trim(substr($line, $pos + 1)); + $headers[$header] = $value; + } + } + fclose($fp); + return $headers; + } + + /** + * Redirect + * + * This function redirects the client. This is done by issuing + * a "Location" header and exiting if wanted. If you set $rfc2616 to true + * HTTP will output a hypertext note with the location of the redirect. + * + * @static + * @access public + * @return mixed Returns true on succes (or exits) or false if headers + * have already been sent. + * @param string $url URL where the redirect should go to. + * @param bool $exit Whether to exit immediately after redirection. + * @param bool $rfc2616 Wheter to output a hypertext note where we're + * redirecting to (Redirecting to ....) + */ + function redirect($url, $exit = true, $rfc2616 = false) + { + if (headers_sent()) { + return false; + } + + $url = HTTP::absoluteURI($url); + header('Location: '. $url); + + if ( $rfc2616 && isset($_SERVER['REQUEST_METHOD']) && + $_SERVER['REQUEST_METHOD'] != 'HEAD') { + printf('Redirecting to: %s.', $url, $url); + } + if ($exit) { + exit; + } + return true; + } + + /** + * Absolute URI + * + * This function returns the absolute URI for the partial URL passed. + * The current scheme (HTTP/HTTPS), host server, port, current script + * location are used if necessary to resolve any relative URLs. + * + * Offsets potentially created by PATH_INFO are taken care of to resolve + * relative URLs to the current script. + * + * You can choose a new protocol while resolving the URI. This is + * particularly useful when redirecting a web browser using relative URIs + * and to switch from HTTP to HTTPS, or vice-versa, at the same time. + * + * @author Philippe Jausions + * @static + * @access public + * @return string The absolute URI. + * @param string $url Absolute or relative URI the redirect should go to. + * @param string $protocol Protocol to use when redirecting URIs. + * @param integer $port A new port number. + */ + function absoluteURI($url = null, $protocol = null, $port = null) + { + // filter CR/LF + $url = str_replace(array("\r", "\n"), ' ', $url); + + // Mess around with already absolute URIs + if (preg_match('!^([a-z0-9]+)://!i', $url)) { + if (empty($protocol) && empty($port)) { + return $url; + } + if (!empty($protocol)) { + $url = $protocol .':'. end($array = explode(':', $url, 2)); + } + if (!empty($port)) { + $url = preg_replace('!^(([a-z0-9]+)://[^/:]+)(:[\d]+)?!i', + '\1:'. $port, $url); + } + return $url; + } + + $host = 'localhost'; + if (!empty($_SERVER['HTTP_HOST'])) { + list($host) = explode(':', $_SERVER['HTTP_HOST']); + } elseif (!empty($_SERVER['SERVER_NAME'])) { + list($host) = explode(':', $_SERVER['SERVER_NAME']); + } + + if (empty($protocol)) { + if (isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'], 'on')) { + $protocol = 'https'; + } else { + $protocol = 'http'; + } + if (!isset($port) || $port != intval($port)) { + $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80; + } + } + + if ($protocol == 'http' && $port == 80) { + unset($port); + } + if ($protocol == 'https' && $port == 443) { + unset($port); + } + + $server = $protocol .'://'. $host . (isset($port) ? ':'. $port : ''); + + if (!strlen($url)) { + $url = isset($_SERVER['REQUEST_URI']) ? + $_SERVER['REQUEST_URI'] : $_SERVER['PHP_SELF']; + } + + if ($url{0} == '/') { + return $server . $url; + } + + // Check for PATH_INFO + if (isset($_SERVER['PATH_INFO']) && strlen($_SERVER['PATH_INFO']) && + $_SERVER['PHP_SELF'] != $_SERVER['PATH_INFO']) { + $path = dirname(substr($_SERVER['PHP_SELF'], 0, -strlen($_SERVER['PATH_INFO']))); + } else { + $path = dirname($_SERVER['PHP_SELF']); + } + + if (substr($path = strtr($path, '\\', '/'), -1) != '/') { + $path .= '/'; + } + + return $server . $path . $url; + } + + /** + * Raise Error + * + * Lazy raising of PEAR_Errors. + * + * @static + * @access protected + * @return object PEAR_Error + * @param mixed $error + * @param int $code + */ + function raiseError($error = null, $code = null) + { + require_once 'PEAR.php'; + return PEAR::raiseError($error, $code); + } +} + +?> diff --git a/common/PEAR/HTTP/Download.php b/common/PEAR/HTTP/Download.php new file mode 100644 index 0000000..51d496a --- /dev/null +++ b/common/PEAR/HTTP/Download.php @@ -0,0 +1,1031 @@ + + * @copyright 2003-2005 Michael Wallner + * @license BSD, revised + * @version CVS: $Id: Download.php,v 1.75 2005/11/13 19:18:53 mike Exp $ + * @link http://pear.php.net/package/HTTP_Download + */ + +// {{{ includes +/** + * Requires PEAR + */ +require_once 'PEAR.php'; + +/** + * Requires HTTP_Header + */ +require_once 'HTTP/Header.php'; +// }}} + +// {{{ constants +/**#@+ Use with HTTP_Download::setContentDisposition() **/ +/** + * Send data as attachment + */ +define('HTTP_DOWNLOAD_ATTACHMENT', 'attachment'); +/** + * Send data inline + */ +define('HTTP_DOWNLOAD_INLINE', 'inline'); +/**#@-**/ + +/**#@+ Use with HTTP_Download::sendArchive() **/ +/** + * Send as uncompressed tar archive + */ +define('HTTP_DOWNLOAD_TAR', 'TAR'); +/** + * Send as gzipped tar archive + */ +define('HTTP_DOWNLOAD_TGZ', 'TGZ'); +/** + * Send as bzip2 compressed tar archive + */ +define('HTTP_DOWNLOAD_BZ2', 'BZ2'); +/** + * Send as zip archive + */ +define('HTTP_DOWNLOAD_ZIP', 'ZIP'); +/**#@-**/ + +/**#@+ + * Error constants + */ +define('HTTP_DOWNLOAD_E_HEADERS_SENT', -1); +define('HTTP_DOWNLOAD_E_NO_EXT_ZLIB', -2); +define('HTTP_DOWNLOAD_E_NO_EXT_MMAGIC', -3); +define('HTTP_DOWNLOAD_E_INVALID_FILE', -4); +define('HTTP_DOWNLOAD_E_INVALID_PARAM', -5); +define('HTTP_DOWNLOAD_E_INVALID_RESOURCE', -6); +define('HTTP_DOWNLOAD_E_INVALID_REQUEST', -7); +define('HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE', -8); +define('HTTP_DOWNLOAD_E_INVALID_ARCHIVE_TYPE', -9); +/**#@-**/ +// }}} + +/** + * Send HTTP Downloads/Responses. + * + * With this package you can handle (hidden) downloads. + * It supports partial downloads, resuming and sending + * raw data ie. from database BLOBs. + * + * ATTENTION: + * You shouldn't use this package together with ob_gzhandler or + * zlib.output_compression enabled in your php.ini, especially + * if you want to send already gzipped data! + * + * @access public + * @version $Revision: 1.75 $ + */ +class HTTP_Download +{ + // {{{ protected member variables + /** + * Path to file for download + * + * @see HTTP_Download::setFile() + * @access protected + * @var string + */ + var $file = ''; + + /** + * Data for download + * + * @see HTTP_Download::setData() + * @access protected + * @var string + */ + var $data = null; + + /** + * Resource handle for download + * + * @see HTTP_Download::setResource() + * @access protected + * @var int + */ + var $handle = null; + + /** + * Whether to gzip the download + * + * @access protected + * @var bool + */ + var $gzip = false; + + /** + * Whether to allow caching of the download on the clients side + * + * @access protected + * @var bool + */ + var $cache = true; + + /** + * Size of download + * + * @access protected + * @var int + */ + var $size = 0; + + /** + * Last modified + * + * @access protected + * @var int + */ + var $lastModified = 0; + + /** + * HTTP headers + * + * @access protected + * @var array + */ + var $headers = array( + 'Content-Type' => 'application/x-octetstream', + 'Pragma' => 'cache', + 'Cache-Control' => 'public, must-revalidate, max-age=0', + 'Accept-Ranges' => 'bytes', + 'X-Sent-By' => 'PEAR::HTTP::Download' + ); + + /** + * HTTP_Header + * + * @access protected + * @var object + */ + var $HTTP = null; + + /** + * ETag + * + * @access protected + * @var string + */ + var $etag = ''; + + /** + * Buffer Size + * + * @access protected + * @var int + */ + var $bufferSize = 2097152; + + /** + * Throttle Delay + * + * @access protected + * @var float + */ + var $throttleDelay = 0; + + /** + * Sent Bytes + * + * @access public + * @var int + */ + var $sentBytes = 0; + // }}} + + // {{{ constructor + /** + * Constructor + * + * Set supplied parameters. + * + * @access public + * @param array $params associative array of parameters + * + * one of: + * o 'file' => path to file for download + * o 'data' => raw data for download + * o 'resource' => resource handle for download + *
+ * and any of: + * o 'cache' => whether to allow cs caching + * o 'gzip' => whether to gzip the download + * o 'lastmodified' => unix timestamp + * o 'contenttype' => content type of download + * o 'contentdisposition' => content disposition + * o 'buffersize' => amount of bytes to buffer + * o 'throttledelay' => amount of secs to sleep + * o 'cachecontrol' => cache privacy and validity + * + *
+ * 'Content-Disposition' is not HTTP compliant, but most browsers + * follow this header, so it was borrowed from MIME standard. + * + * It looks like this:
+ * "Content-Disposition: attachment; filename=example.tgz". + * + * @see HTTP_Download::setContentDisposition() + */ + function HTTP_Download($params = array()) + { + $this->HTTP = &new HTTP_Header; + $this->setParams($params); + } + // }}} + + // {{{ public methods + /** + * Set parameters + * + * Set supplied parameters through its accessor methods. + * + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param array $params associative array of parameters + * + * @see HTTP_Download::HTTP_Download() + */ + function setParams($params) + { + foreach((array) $params as $param => $value){ + $method = 'set'. $param; + + if (!method_exists($this, $method)) { + return PEAR::raiseError( + "Method '$method' doesn't exist.", + HTTP_DOWNLOAD_E_INVALID_PARAM + ); + } + + $e = call_user_func_array(array(&$this, $method), (array) $value); + + if (PEAR::isError($e)) { + return $e; + } + } + return true; + } + + /** + * Set path to file for download + * + * The Last-Modified header will be set to files filemtime(), actually. + * Returns PEAR_Error (HTTP_DOWNLOAD_E_INVALID_FILE) if file doesn't exist. + * Sends HTTP 404 status if $send_404 is set to true. + * + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param string $file path to file for download + * @param bool $send_404 whether to send HTTP/404 if + * the file wasn't found + */ + function setFile($file, $send_404 = true) + { + $file = realpath($file); + if (!is_file($file)) { + if ($send_404) { + $this->HTTP->sendStatusCode(404); + } + return PEAR::raiseError( + "File '$file' not found.", + HTTP_DOWNLOAD_E_INVALID_FILE + ); + } + $this->setLastModified(filemtime($file)); + $this->file = $file; + $this->size = filesize($file); + return true; + } + + /** + * Set data for download + * + * Set $data to null if you want to unset this. + * + * @access public + * @return void + * @param $data raw data to send + */ + function setData($data = null) + { + $this->data = $data; + $this->size = strlen($data); + } + + /** + * Set resource for download + * + * The resource handle supplied will be closed after sending the download. + * Returns a PEAR_Error (HTTP_DOWNLOAD_E_INVALID_RESOURCE) if $handle + * is no valid resource. Set $handle to null if you want to unset this. + * + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param int $handle resource handle + */ + function setResource($handle = null) + { + if (!isset($handle)) { + $this->handle = null; + $this->size = 0; + return true; + } + + if (is_resource($handle)) { + $this->handle = $handle; + $filestats = fstat($handle); + $this->size = $filestats['size']; + return true; + } + + return PEAR::raiseError( + "Handle '$handle' is no valid resource.", + HTTP_DOWNLOAD_E_INVALID_RESOURCE + ); + } + + /** + * Whether to gzip the download + * + * Returns a PEAR_Error (HTTP_DOWNLOAD_E_NO_EXT_ZLIB) + * if ext/zlib is not available/loadable. + * + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param bool $gzip whether to gzip the download + */ + function setGzip($gzip = false) + { + if ($gzip && !PEAR::loadExtension('zlib')){ + return PEAR::raiseError( + 'GZIP compression (ext/zlib) not available.', + HTTP_DOWNLOAD_E_NO_EXT_ZLIB + ); + } + $this->gzip = (bool) $gzip; + return true; + } + + /** + * Whether to allow caching + * + * If set to true (default) we'll send some headers that are commonly + * used for caching purposes like ETag, Cache-Control and Last-Modified. + * + * If caching is disabled, we'll send the download no matter if it + * would actually be cached at the client side. + * + * @access public + * @return void + * @param bool $cache whether to allow caching + */ + function setCache($cache = true) + { + $this->cache = (bool) $cache; + } + + /** + * Whether to allow proxies to cache + * + * If set to 'private' proxies shouldn't cache the response. + * This setting defaults to 'public' and affects only cached responses. + * + * @access public + * @return bool + * @param string $cache private or public + * @param int $maxage maximum age of the client cache entry + */ + function setCacheControl($cache = 'public', $maxage = 0) + { + switch ($cache = strToLower($cache)) + { + case 'private': + case 'public': + $this->headers['Cache-Control'] = + $cache .', must-revalidate, max-age='. abs($maxage); + return true; + break; + } + return false; + } + + /** + * Set ETag + * + * Sets a user-defined ETag for cache-validation. The ETag is usually + * generated by HTTP_Download through its payload information. + * + * @access public + * @return void + * @param string $etag Entity tag used for strong cache validation. + */ + function setETag($etag = null) + { + $this->etag = (string) $etag; + } + + /** + * Set Size of Buffer + * + * The amount of bytes specified as buffer size is the maximum amount + * of data read at once from resources or files. The default size is 2M + * (2097152 bytes). Be aware that if you enable gzip compression and + * you set a very low buffer size that the actual file size may grow + * due to added gzip headers for each sent chunk of the specified size. + * + * Returns PEAR_Error (HTTP_DOWNLOAD_E_INVALID_PARAM) if $size is not + * greater than 0 bytes. + * + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param int $bytes Amount of bytes to use as buffer. + */ + function setBufferSize($bytes = 2097152) + { + if (0 >= $bytes) { + return PEAR::raiseError( + 'Buffer size must be greater than 0 bytes ('. $bytes .' given)', + HTTP_DOWNLOAD_E_INVALID_PARAM); + } + $this->bufferSize = abs($bytes); + return true; + } + + /** + * Set Throttle Delay + * + * Set the amount of seconds to sleep after each chunck that has been + * sent. One can implement some sort of throttle through adjusting the + * buffer size and the throttle delay. With the following settings + * HTTP_Download will sleep a second after each 25 K of data sent. + * + * + * Array( + * 'throttledelay' => 1, + * 'buffersize' => 1024 * 25, + * ) + * + * + * Just be aware that if gzipp'ing is enabled, decreasing the chunk size + * too much leads to proportionally increased network traffic due to added + * gzip header and bottom bytes around each chunk. + * + * @access public + * @return void + * @param float $seconds Amount of seconds to sleep after each + * chunk that has been sent. + */ + function setThrottleDelay($seconds = 0) + { + $this->throttleDelay = abs($seconds) * 1000; + } + + /** + * Set "Last-Modified" + * + * This is usually determined by filemtime() in HTTP_Download::setFile() + * If you set raw data for download with HTTP_Download::setData() and you + * want do send an appropiate "Last-Modified" header, you should call this + * method. + * + * @access public + * @return void + * @param int unix timestamp + */ + function setLastModified($last_modified) + { + $this->lastModified = $this->headers['Last-Modified'] = (int) $last_modified; + } + + /** + * Set Content-Disposition header + * + * @see HTTP_Download::HTTP_Download + * + * @access public + * @return void + * @param string $disposition whether to send the download + * inline or as attachment + * @param string $file_name the filename to display in + * the browser's download window + * + * Example: + * + * $HTTP_Download->setContentDisposition( + * HTTP_DOWNLOAD_ATTACHMENT, + * 'download.tgz' + * ); + * + */ + function setContentDisposition( $disposition = HTTP_DOWNLOAD_ATTACHMENT, + $file_name = null) + { + $cd = $disposition; + if (isset($file_name)) { + $cd .= '; filename="' . $file_name . '"'; + } elseif ($this->file) { + $cd .= '; filename="' . basename($this->file) . '"'; + } + $this->headers['Content-Disposition'] = $cd; + } + + /** + * Set content type of the download + * + * Default content type of the download will be 'application/x-octetstream'. + * Returns PEAR_Error (HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE) if + * $content_type doesn't seem to be valid. + * + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param string $content_type content type of file for download + */ + function setContentType($content_type = 'application/x-octetstream') + { + if (!preg_match('/^[a-z]+\w*\/[a-z]+[\w.;= -]*$/', $content_type)) { + return PEAR::raiseError( + "Invalid content type '$content_type' supplied.", + HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE + ); + } + $this->headers['Content-Type'] = $content_type; + return true; + } + + /** + * Guess content type of file + * + * First we try to use PEAR::MIME_Type, if installed, to detect the content + * type, else we check if ext/mime_magic is loaded and properly configured. + * + * Returns PEAR_Error if: + * o if PEAR::MIME_Type failed to detect a proper content type + * (HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE) + * o ext/magic.mime is not installed, or not properly configured + * (HTTP_DOWNLOAD_E_NO_EXT_MMAGIC) + * o mime_content_type() couldn't guess content type or returned + * a content type considered to be bogus by setContentType() + * (HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE) + * + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + */ + function guessContentType() + { + if (class_exists('MIME_Type') || @include_once 'MIME/Type.php') { + if (PEAR::isError($mime_type = MIME_Type::autoDetect($this->file))) { + return PEAR::raiseError($mime_type->getMessage(), + HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE); + } + return $this->setContentType($mime_type); + } + if (!function_exists('mime_content_type')) { + return PEAR::raiseError( + 'This feature requires ext/mime_magic!', + HTTP_DOWNLOAD_E_NO_EXT_MMAGIC + ); + } + if (!is_file(ini_get('mime_magic.magicfile'))) { + return PEAR::raiseError( + 'ext/mime_magic is loaded but not properly configured!', + HTTP_DOWNLOAD_E_NO_EXT_MMAGIC + ); + } + if (!$content_type = @mime_content_type($this->file)) { + return PEAR::raiseError( + 'Couldn\'t guess content type with mime_content_type().', + HTTP_DOWNLOAD_E_INVALID_CONTENT_TYPE + ); + } + return $this->setContentType($content_type); + } + + /** + * Send + * + * Returns PEAR_Error if: + * o HTTP headers were already sent (HTTP_DOWNLOAD_E_HEADERS_SENT) + * o HTTP Range was invalid (HTTP_DOWNLOAD_E_INVALID_REQUEST) + * + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param bool $autoSetContentDisposition Whether to set the + * Content-Disposition header if it isn't already. + */ + function send($autoSetContentDisposition = true) + { + if (headers_sent()) { + return PEAR::raiseError( + 'Headers already sent.', + HTTP_DOWNLOAD_E_HEADERS_SENT + ); + } + + if (!ini_get('safe_mode')) { + @set_time_limit(0); + } + + if ($autoSetContentDisposition && + !isset($this->headers['Content-Disposition'])) { + $this->setContentDisposition(); + } + + if ($this->cache) { + $this->headers['ETag'] = $this->generateETag(); + if ($this->isCached()) { + $this->HTTP->sendStatusCode(304); + $this->sendHeaders(); + return true; + } + } else { + unset($this->headers['Last-Modified']); + } + + while (@ob_end_clean()); + + if ($this->gzip) { + @ob_start('ob_gzhandler'); + } else { + ob_start(); + } + + $this->sentBytes = 0; + + if ($this->isRangeRequest()) { + $this->HTTP->sendStatusCode(206); + $chunks = $this->getChunks(); + } else { + $this->HTTP->sendStatusCode(200); + $chunks = array(array(0, $this->size)); + if (!$this->gzip && count(ob_list_handlers()) < 2) { + $this->headers['Content-Length'] = $this->size; + } + } + + if (PEAR::isError($e = $this->sendChunks($chunks))) { + ob_end_clean(); + $this->HTTP->sendStatusCode(416); + return $e; + } + + ob_end_flush(); + flush(); + return true; + } + + /** + * Static send + * + * @see HTTP_Download::HTTP_Download() + * @see HTTP_Download::send() + * + * @static + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param array $params associative array of parameters + * @param bool $guess whether HTTP_Download::guessContentType() + * should be called + */ + function staticSend($params, $guess = false) + { + $d = &new HTTP_Download(); + $e = $d->setParams($params); + if (PEAR::isError($e)) { + return $e; + } + if ($guess) { + $e = $d->guessContentType(); + if (PEAR::isError($e)) { + return $e; + } + } + return $d->send(); + } + + /** + * Send a bunch of files or directories as an archive + * + * Example: + * + * require_once 'HTTP/Download.php'; + * HTTP_Download::sendArchive( + * 'myArchive.tgz', + * '/var/ftp/pub/mike', + * HTTP_DOWNLOAD_TGZ, + * '', + * '/var/ftp/pub' + * ); + * + * + * @see Archive_Tar::createModify() + * @deprecated use HTTP_Download_Archive::send() + * @static + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param string $name name the sent archive should have + * @param mixed $files files/directories + * @param string $type archive type + * @param string $add_path path that should be prepended to the files + * @param string $strip_path path that should be stripped from the files + */ + function sendArchive( $name, + $files, + $type = HTTP_DOWNLOAD_TGZ, + $add_path = '', + $strip_path = '') + { + require_once 'HTTP/Download/Archive.php'; + return HTTP_Download_Archive::send($name, $files, $type, + $add_path, $strip_path); + } + // }}} + + // {{{ protected methods + /** + * Generate ETag + * + * @access protected + * @return string + */ + function generateETag() + { + if (!$this->etag) { + if ($this->data) { + $md5 = md5($this->data); + } else { + $fst = is_resource($this->handle) ? + fstat($this->handle) : stat($this->file); + $md5 = md5($fst['mtime'] .'='. $fst['ino'] .'='. $fst['size']); + } + $this->etag = '"' . $md5 . '-' . crc32($md5) . '"'; + } + return $this->etag; + } + + /** + * Send multiple chunks + * + * @access protected + * @return mixed Returns true on success or PEAR_Error on failure. + * @param array $chunks + */ + function sendChunks($chunks) + { + if (count($chunks) == 1) { + return $this->sendChunk(array_shift($chunks)); + } + + $bound = uniqid('HTTP_DOWNLOAD-', true); + $cType = $this->headers['Content-Type']; + $this->headers['Content-Type'] = + 'multipart/byteranges; boundary=' . $bound; + $this->sendHeaders(); + foreach ($chunks as $chunk){ + if (PEAR::isError($e = $this->sendChunk($chunk, $cType, $bound))) { + return $e; + } + } + #echo "\r\n--$bound--\r\n"; + return true; + } + + /** + * Send chunk of data + * + * @access protected + * @return mixed Returns true on success or PEAR_Error on failure. + * @param array $chunk start and end offset of the chunk to send + * @param string $cType actual content type + * @param string $bound boundary for multipart/byteranges + */ + function sendChunk($chunk, $cType = null, $bound = null) + { + list($offset, $lastbyte) = $chunk; + $length = ($lastbyte - $offset) + 1; + + if ($length < 1) { + return PEAR::raiseError( + "Error processing range request: $offset-$lastbyte/$length", + HTTP_DOWNLOAD_E_INVALID_REQUEST + ); + } + + $range = $offset . '-' . $lastbyte . '/' . $this->size; + + if (isset($cType, $bound)) { + echo "\r\n--$bound\r\n", + "Content-Type: $cType\r\n", + "Content-Range: bytes $range\r\n\r\n"; + } else { + if ($this->isRangeRequest()) { + $this->headers['Content-Range'] = 'bytes '. $range; + } + $this->sendHeaders(); + } + + if ($this->data) { + while (($length -= $this->bufferSize) > 0) { + $this->flush(substr($this->data, $offset, $this->bufferSize)); + $this->throttleDelay and $this->sleep(); + $offset += $this->bufferSize; + } + if ($length) { + $this->flush(substr($this->data, $offset, $this->bufferSize + $length)); + } + } else { + if (!is_resource($this->handle)) { + $this->handle = fopen($this->file, 'rb'); + } + fseek($this->handle, $offset); + while (($length -= $this->bufferSize) > 0) { + $this->flush(fread($this->handle, $this->bufferSize)); + $this->throttleDelay and $this->sleep(); + } + if ($length) { + $this->flush(fread($this->handle, $this->bufferSize + $length)); + } + } + return true; + } + + /** + * Get chunks to send + * + * @access protected + * @return array + */ + function getChunks() + { + $parts = array(); + foreach (explode(',', $this->getRanges()) as $chunk){ + list($o, $e) = explode('-', $chunk); + if ($e >= $this->size || (empty($e) && $e !== 0 && $e !== '0')) { + $e = $this->size - 1; + } + if (empty($o) && $o !== 0 && $o !== '0') { + $o = $this->size - $e; + $e = $this->size - 1; + } + $parts[] = array($o, $e); + } + return $parts; + } + + /** + * Check if range is requested + * + * @access protected + * @return bool + */ + function isRangeRequest() + { + if (!isset($_SERVER['HTTP_RANGE'])) { + return false; + } + return $this->isValidRange(); + } + + /** + * Get range request + * + * @access protected + * @return array + */ + function getRanges() + { + return preg_match('/^bytes=((\d*-\d*,? ?)+)$/', + @$_SERVER['HTTP_RANGE'], $matches) ? $matches[1] : array(); + } + + /** + * Check if entity is cached + * + * @access protected + * @return bool + */ + function isCached() + { + return ( + (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && + $this->lastModified == strtotime(current($a = explode( + ';', $_SERVER['HTTP_IF_MODIFIED_SINCE'])))) || + (isset($_SERVER['HTTP_IF_NONE_MATCH']) && + $this->compareAsterisk('HTTP_IF_NONE_MATCH', $this->etag)) + ); + } + + /** + * Check if entity hasn't changed + * + * @access protected + * @return bool + */ + function isValidRange() + { + if (isset($_SERVER['HTTP_IF_MATCH']) && + !$this->compareAsterisk('HTTP_IF_MATCH', $this->etag)) { + return false; + } + if (isset($_SERVER['HTTP_IF_RANGE']) && + $_SERVER['HTTP_IF_RANGE'] !== $this->etag && + strtotime($_SERVER['HTTP_IF_RANGE']) !== $this->lastModified) { + return false; + } + if (isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE'])) { + $lm = array_shift(explode(';', $_SERVER['HTTP_IF_UNMODIFIED_SINCE'])); + if (strtotime($lm) !== $this->lastModified) { + return false; + } + } + if (isset($_SERVER['HTTP_UNLESS_MODIFIED_SINCE'])) { + $lm = array_shift(explode(';', $_SERVER['HTTP_UNLESS_MODIFIED_SINCE'])); + if (strtotime($lm) !== $this->lastModified) { + return false; + } + } + return true; + } + + /** + * Compare against an asterisk or check for equality + * + * @access protected + * @return bool + * @param string key for the $_SERVER array + * @param string string to compare + */ + function compareAsterisk($svar, $compare) + { + foreach (array_map('trim', explode(',', $_SERVER[$svar])) as $request) { + if ($request === '*' || $request === $compare) { + return true; + } + } + return false; + } + + /** + * Send HTTP headers + * + * @access protected + * @return void + */ + function sendHeaders() + { + foreach ($this->headers as $header => $value) { + $this->HTTP->setHeader($header, $value); + } + $this->HTTP->sendHeaders(); + /* NSAPI won't output anything if we did this */ + if (strncasecmp(PHP_SAPI, 'nsapi', 5)) { + ob_flush(); + flush(); + } + } + + /** + * Flush + * + * @access protected + * @return void + * @param string $data + */ + function flush($data = '') + { + if ($dlen = strlen($data)) { + $this->sentBytes += $dlen; + echo $data; + } + ob_flush(); + flush(); + } + + /** + * Sleep + * + * @access protected + * @return void + */ + function sleep() + { + if (OS_WINDOWS) { + com_message_pump($this->throttleDelay); + } else { + usleep($this->throttleDelay * 1000); + } + } + // }}} +} +?> diff --git a/common/PEAR/HTTP/Download/Archive.php b/common/PEAR/HTTP/Download/Archive.php new file mode 100644 index 0000000..2aa5b8b --- /dev/null +++ b/common/PEAR/HTTP/Download/Archive.php @@ -0,0 +1,122 @@ + + * @copyright 2003-2005 Michael Wallner + * @license BSD, revisewd + * @version CVS: $Id: Archive.php,v 1.4 2005/11/13 19:18:55 mike Exp $ + * @link http://pear.php.net/package/HTTP_Download + */ + +/** + * Requires HTTP_Download + */ +require_once 'HTTP/Download.php'; + +/** + * Requires System + */ +require_once 'System.php'; + +/** + * HTTP_Download_Archive + * + * Helper class for sending Archives. + * + * @access public + * @version $Revision: 1.4 $ + */ +class HTTP_Download_Archive +{ + /** + * Send a bunch of files or directories as an archive + * + * Example: + * + * require_once 'HTTP/Download/Archive.php'; + * HTTP_Download_Archive::send( + * 'myArchive.tgz', + * '/var/ftp/pub/mike', + * HTTP_DOWNLOAD_BZ2, + * '', + * '/var/ftp/pub' + * ); + * + * + * @see Archive_Tar::createModify() + * @static + * @access public + * @return mixed Returns true on success or PEAR_Error on failure. + * @param string $name name the sent archive should have + * @param mixed $files files/directories + * @param string $type archive type + * @param string $add_path path that should be prepended to the files + * @param string $strip_path path that should be stripped from the files + */ + function send($name, $files, $type = HTTP_DOWNLOAD_TGZ, $add_path = '', $strip_path = '') + { + $tmp = System::mktemp(); + + switch ($type = strToUpper($type)) + { + case HTTP_DOWNLOAD_TAR: + include_once 'Archive/Tar.php'; + $arc = &new Archive_Tar($tmp); + $content_type = 'x-tar'; + break; + + case HTTP_DOWNLOAD_TGZ: + include_once 'Archive/Tar.php'; + $arc = &new Archive_Tar($tmp, 'gz'); + $content_type = 'x-gzip'; + break; + + case HTTP_DOWNLOAD_BZ2: + include_once 'Archive/Tar.php'; + $arc = &new Archive_Tar($tmp, 'bz2'); + $content_type = 'x-bzip2'; + break; + + case HTTP_DOWNLOAD_ZIP: + include_once 'Archive/Zip.php'; + $arc = &new Archive_Zip($tmp); + $content_type = 'x-zip'; + break; + + default: + return PEAR::raiseError( + 'Archive type not supported: ' . $type, + HTTP_DOWNLOAD_E_INVALID_ARCHIVE_TYPE + ); + } + + if ($type == HTTP_DOWNLOAD_ZIP) { + $options = array( 'add_path' => $add_path, + 'remove_path' => $strip_path); + if (!$arc->create($files, $options)) { + return PEAR::raiseError('Archive creation failed.'); + } + } else { + if (!$e = $arc->createModify($files, $add_path, $strip_path)) { + return PEAR::raiseError('Archive creation failed.'); + } + if (PEAR::isError($e)) { + return $e; + } + } + unset($arc); + + $dl = &new HTTP_Download(array('file' => $tmp)); + $dl->setContentType('application/' . $content_type); + $dl->setContentDisposition(HTTP_DOWNLOAD_ATTACHMENT, $name); + return $dl->send(); + } +} +?> diff --git a/common/PEAR/HTTP/Download/PgLOB.php b/common/PEAR/HTTP/Download/PgLOB.php new file mode 100644 index 0000000..19de2bc --- /dev/null +++ b/common/PEAR/HTTP/Download/PgLOB.php @@ -0,0 +1,177 @@ + + * @copyright 2003-2005 Michael Wallner + * @license BSD, revised + * @version CVS: $Id: PgLOB.php,v 1.14 2005/11/13 19:18:55 mike Exp $ + * @link http://pear.php.net/package/HTTP_Download + */ + +$GLOBALS['_HTTP_Download_PgLOB_Connection'] = null; +stream_register_wrapper('pglob', 'HTTP_Download_PgLOB'); + +/** + * PgSQL large object stream interface for HTTP_Download + * + * Usage: + * + * require_once 'HTTP/Download.php'; + * require_once 'HTTP/Download/PgLOB.php'; + * $db = &DB::connect('pgsql://user:pass@host/db'); + * // or $db = pg_connect(...); + * $lo = HTTP_Download_PgLOB::open($db, 12345); + * $dl = &new HTTP_Download; + * $dl->setResource($lo); + * $dl->send() + * + * + * @access public + * @version $Revision: 1.14 $ + */ +class HTTP_Download_PgLOB +{ + /** + * Set Connection + * + * @static + * @access public + * @return bool + * @param mixed $conn + */ + function setConnection($conn) + { + if (is_a($conn, 'DB_Common')) { + $conn = $conn->dbh; + } elseif ( is_a($conn, 'MDB_Common') || + is_a($conn, 'MDB2_Driver_Common')) { + $conn = $conn->connection; + } + if ($isResource = is_resource($conn)) { + $GLOBALS['_HTTP_Download_PgLOB_Connection'] = $conn; + } + return $isResource; + } + + /** + * Get Connection + * + * @static + * @access public + * @return resource + */ + function getConnection() + { + if (is_resource($GLOBALS['_HTTP_Download_PgLOB_Connection'])) { + return $GLOBALS['_HTTP_Download_PgLOB_Connection']; + } + return null; + } + + /** + * Open + * + * @static + * @access public + * @return resource + * @param mixed $conn + * @param int $loid + * @param string $mode + */ + function open($conn, $loid, $mode = 'rb') + { + HTTP_Download_PgLOB::setConnection($conn); + return fopen('pglob:///'. $loid, $mode); + } + + /**#@+ + * Stream Interface Implementation + * @internal + */ + var $ID = 0; + var $size = 0; + var $conn = null; + var $handle = null; + + function stream_open($path, $mode) + { + if (!$this->conn = HTTP_Download_PgLOB::getConnection()) { + return false; + } + if (!preg_match('/(\d+)/', $path, $matches)) { + return false; + } + $this->ID = $matches[1]; + + if (!pg_query($this->conn, 'BEGIN')) { + return false; + } + + $this->handle = pg_lo_open($this->conn, $this->ID, $mode); + if (!is_resource($this->handle)) { + return false; + } + + // fetch size of lob + pg_lo_seek($this->handle, 0, PGSQL_SEEK_END); + $this->size = (int) pg_lo_tell($this->handle); + pg_lo_seek($this->handle, 0, PGSQL_SEEK_SET); + + return true; + } + + function stream_read($length) + { + return pg_lo_read($this->handle, $length); + } + + function stream_seek($offset, $whence = SEEK_SET) + { + return pg_lo_seek($this->handle, $offset, $whence); + } + + function stream_tell() + { + return pg_lo_tell($this->handle); + } + + function stream_eof() + { + return pg_lo_tell($this->handle) >= $this->size; + } + + function stream_flush() + { + return true; + } + + function stream_stat() + { + return array('size' => $this->size, 'ino' => $this->ID); + } + + function stream_write($data) + { + return pg_lo_write($this->handle, $data); + } + + function stream_close() + { + if (pg_lo_close($this->handle)) { + return pg_query($this->conn, 'COMMIT'); + } else { + pg_query($this->conn ,'ROLLBACK'); + return false; + } + } + /**#@-*/ +} + +?> diff --git a/common/PEAR/HTTP/Header.php b/common/PEAR/HTTP/Header.php new file mode 100644 index 0000000..fd6c497 --- /dev/null +++ b/common/PEAR/HTTP/Header.php @@ -0,0 +1,531 @@ + + * @author Davey Shafik + * @author Michael Wallner + * @copyright 2003-2005 The Authors + * @license BSD, revised + * @version CVS: $Id: Header.php,v 1.32 2005/11/08 19:06:10 mike Exp $ + * @link http://pear.php.net/package/HTTP_Header + */ + +/** + * Requires HTTP + */ +require_once 'HTTP.php'; + +/**#@+ + * Information Codes + */ +define('HTTP_HEADER_STATUS_100', '100 Continue'); +define('HTTP_HEADER_STATUS_101', '101 Switching Protocols'); +define('HTTP_HEADER_STATUS_102', '102 Processing'); +define('HTTP_HEADER_STATUS_INFORMATIONAL',1); +/**#@-*/ + +/**#+ + * Success Codes + */ +define('HTTP_HEADER_STATUS_200', '200 OK'); +define('HTTP_HEADER_STATUS_201', '201 Created'); +define('HTTP_HEADER_STATUS_202', '202 Accepted'); +define('HTTP_HEADER_STATUS_203', '203 Non-Authoritative Information'); +define('HTTP_HEADER_STATUS_204', '204 No Content'); +define('HTTP_HEADER_STATUS_205', '205 Reset Content'); +define('HTTP_HEADER_STATUS_206', '206 Partial Content'); +define('HTTP_HEADER_STATUS_207', '207 Multi-Status'); +define('HTTP_HEADER_STATUS_SUCCESSFUL',2); +/**#@-*/ + +/**#@+ + * Redirection Codes + */ +define('HTTP_HEADER_STATUS_300', '300 Multiple Choices'); +define('HTTP_HEADER_STATUS_301', '301 Moved Permanently'); +define('HTTP_HEADER_STATUS_302', '302 Found'); +define('HTTP_HEADER_STATUS_303', '303 See Other'); +define('HTTP_HEADER_STATUS_304', '304 Not Modified'); +define('HTTP_HEADER_STATUS_305', '305 Use Proxy'); +define('HTTP_HEADER_STATUS_306', '306 (Unused)'); +define('HTTP_HEADER_STATUS_307', '307 Temporary Redirect'); +define('HTTP_HEADER_STATUS_REDIRECT',3); +/**#@-*/ + +/**#@+ + * Error Codes + */ +define('HTTP_HEADER_STATUS_400', '400 Bad Request'); +define('HTTP_HEADER_STATUS_401', '401 Unauthorized'); +define('HTTP_HEADER_STATUS_402', '402 Payment Granted'); +define('HTTP_HEADER_STATUS_403', '403 Forbidden'); +define('HTTP_HEADER_STATUS_404', '404 File Not Found'); +define('HTTP_HEADER_STATUS_405', '405 Method Not Allowed'); +define('HTTP_HEADER_STATUS_406', '406 Not Acceptable'); +define('HTTP_HEADER_STATUS_407', '407 Proxy Authentication Required'); +define('HTTP_HEADER_STATUS_408', '408 Request Time-out'); +define('HTTP_HEADER_STATUS_409', '409 Conflict'); +define('HTTP_HEADER_STATUS_410', '410 Gone'); +define('HTTP_HEADER_STATUS_411', '411 Length Required'); +define('HTTP_HEADER_STATUS_412', '412 Precondition Failed'); +define('HTTP_HEADER_STATUS_413', '413 Request Entity Too Large'); +define('HTTP_HEADER_STATUS_414', '414 Request-URI Too Large'); +define('HTTP_HEADER_STATUS_415', '415 Unsupported Media Type'); +define('HTTP_HEADER_STATUS_416', '416 Requested range not satisfiable'); +define('HTTP_HEADER_STATUS_417', '417 Expectation Failed'); +define('HTTP_HEADER_STATUS_422', '422 Unprocessable Entity'); +define('HTTP_HEADER_STATUS_423', '423 Locked'); +define('HTTP_HEADER_STATUS_424', '424 Failed Dependency'); +define('HTTP_HEADER_STATUS_CLIENT_ERROR',4); +/**#@-*/ + +/**#@+ + * Server Errors + */ +define('HTTP_HEADER_STATUS_500', '500 Internal Server Error'); +define('HTTP_HEADER_STATUS_501', '501 Not Implemented'); +define('HTTP_HEADER_STATUS_502', '502 Bad Gateway'); +define('HTTP_HEADER_STATUS_503', '503 Service Unavailable'); +define('HTTP_HEADER_STATUS_504', '504 Gateway Time-out'); +define('HTTP_HEADER_STATUS_505', '505 HTTP Version not supported'); +define('HTTP_HEADER_STATUS_507', '507 Insufficient Storage'); +define('HTTP_HEADER_STATUS_SERVER_ERROR',5); +/**#@-*/ + +/** + * HTTP_Header + * + * @package HTTP_Header + * @category HTTP + * @access public + * @version $Revision: 1.32 $ + */ +class HTTP_Header extends HTTP +{ + /** + * Default Headers + * + * The values that are set as default, are the same as PHP sends by default. + * + * @var array + * @access private + */ + var $_headers = array( + 'content-type' => 'text/html', + 'pragma' => 'no-cache', + 'cache-control' => 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0' + ); + + /** + * HTTP version + * + * @var string + * @access private + */ + var $_httpVersion = '1.0'; + + /** + * Constructor + * + * Sets HTTP version. + * + * @access public + * @return object HTTP_Header + */ + function HTTP_Header() + { + if (isset($_SERVER['SERVER_PROTOCOL'])) { + $this->setHttpVersion(substr($_SERVER['SERVER_PROTOCOL'], -3)); + } + } + + /** + * Set HTTP version + * + * @access public + * @return bool Returns true on success or false if version doesn't + * match 1.0 or 1.1 (note: 1 will result in 1.0) + * @param mixed $version HTTP version, either 1.0 or 1.1 + */ + function setHttpVersion($version) + { + $version = round((float) $version, 1); + if ($version < 1.0 || $version > 1.1) { + return false; + } + $this->_httpVersion = sprintf('%0.1f', $version); + return true; + } + + /** + * Get HTTP version + * + * @access public + * @return string + */ + function getHttpVersion() + { + return $this->_httpVersion; + } + + /** + * Set Header + * + * The default value for the Last-Modified header will be current + * date and atime if $value is omitted. + * + * @access public + * @return bool Returns true on success or false if $key was empty or + * $value was not of an scalar type. + * @param string $key The name of the header. + * @param string $value The value of the header. (NULL to unset header) + */ + function setHeader($key, $value = null) + { + if (empty($key) || (isset($value) && !is_scalar($value))) { + return false; + } + + $key = strToLower($key); + if ($key == 'last-modified') { + if (!isset($value)) { + $value = HTTP::Date(time()); + } elseif (is_numeric($value)) { + $value = HTTP::Date($value); + } + } + + if (isset($value)) { + $this->_headers[$key] = $value; + } else { + unset($this->_headers[$key]); + } + + return true; + } + + /** + * Get Header + * + * If $key is omitted, all stored headers will be returned. + * + * @access public + * @return mixed Returns string value of the requested header, + * array values of all headers or false if header $key + * is not set. + * @param string $key The name of the header to fetch. + */ + function getHeader($key = null) + { + if (!isset($key)) { + return $this->_headers; + } + + $key = strToLower($key); + + if (!isset($this->_headers[$key])) { + return false; + } + + return $this->_headers[$key]; + } + + /** + * Send Headers + * + * Send out the header that you set via setHeader(). + * + * @access public + * @return bool Returns true on success or false if headers are already + * sent. + * @param array $keys Headers to (not) send, see $include. + * @param array $include If true only $keys matching headers will be + * sent, if false only header not matching $keys will be + * sent. + */ + function sendHeaders($keys = array(), $include = true) + { + if (headers_sent()) { + return false; + } + + if (count($keys)) { + array_change_key_case($keys, CASE_LOWER); + foreach ($this->_headers as $key => $value) { + if ($include ? in_array($key, $keys) : !in_array($key, $keys)) { + header($key .': '. $value); + } + } + } else { + foreach ($this->_headers as $header => $value) { + header($header .': '. $value); + } + } + return true; + } + + /** + * Send Satus Code + * + * Send out the given HTTP-Status code. Use this for example when you + * want to tell the client this page is cached, then you would call + * sendStatusCode(304). + * + * @see HTTP_Header_Cache::exitIfCached() + * + * @access public + * @return bool Returns true on success or false if headers are already + * sent. + * @param int $code The status code to send, i.e. 404, 304, 200, etc. + */ + function sendStatusCode($code) + { + if (headers_sent()) { + return false; + } + + if ($code == (int) $code && defined('HTTP_HEADER_STATUS_'. $code)) { + $code = constant('HTTP_HEADER_STATUS_'. $code); + } + + if (strncasecmp(PHP_SAPI, 'cgi', 3)) { + header('HTTP/'. $this->_httpVersion .' '. $code); + } else { + header('Status: '. $code); + } + return true; + } + + /** + * Date to Timestamp + * + * Converts dates like + * Mon, 31 Mar 2003 15:26:34 GMT + * Tue, 15 Nov 1994 12:45:26 GMT + * into a timestamp, strtotime() didn't do it in older versions. + * + * @deprecated Use PHPs strtotime() instead. + * @access public + * @return mixed Returns int unix timestamp or false if the date doesn't + * seem to be a valid GMT date. + * @param string $date The GMT date. + */ + function dateToTimestamp($date) + { + static $months = array( + null => 0, 'Jan' => 1, 'Feb' => 2, 'Mar' => 3, 'Apr' => 4, + 'May' => 5, 'Jun' => 6, 'Jul' => 7, 'Aug' => 8, 'Sep' => 9, + 'Oct' => 10, 'Nov' => 11, 'Dec' => 12 + ); + + if (-1 < $timestamp = strToTime($date)) { + return $timestamp; + } + + if (!preg_match('~[^,]*,\s(\d+)\s(\w+)\s(\d+)\s(\d+):(\d+):(\d+).*~', + $date, $m)) { + return false; + } + + // [0] => Mon, 31 Mar 2003 15:42:55 GMT + // [1] => 31 [2] => Mar [3] => 2003 [4] => 15 [5] => 42 [6] => 55 + return mktime($m[4], $m[5], $m[6], $months[$m[2]], $m[1], $m[3]); + } + + /** + * Redirect + * + * This function redirects the client. This is done by issuing a Location + * header and exiting. Additionally to HTTP::redirect() you can also add + * parameters to the url. + * + * If you dont need parameters to be added, simply use HTTP::redirect() + * otherwise use HTTP_Header::redirect(). + * + * @see HTTP::redirect() + * @author Wolfram Kriesing + * @access public + * @return void + * @param string $url The URL to redirect to, if none is given it + * redirects to the current page. + * @param array $param Array of query string parameters to add; usually + * a set of key => value pairs; if an array entry consists + * only of an value it is used as key and the respective + * value is fetched from $GLOBALS[$value] + * @param bool $session Whether the session name/id should be added + */ + function redirect($url = null, $param = array(), $session = false) + { + if (!isset($url)) { + $url = $_SERVER['PHP_SELF']; + } + + $qs = array(); + + if ($session) { + $qs[] = session_name() .'='. session_id(); + } + + if (is_array($param) && count($param)) { + if (count($param)) { + foreach ($param as $key => $val) { + if (is_string($key)) { + $qs[] = urlencode($key) .'='. urlencode($val); + } else { + $qs[] = urlencode($val) .'='. urlencode(@$GLOBALS[$val]); + } + } + } + } + + if ($qstr = implode('&', $qs)) { + $purl = parse_url($url); + $url .= (isset($purl['query']) ? '&' : '?') . $qstr; + } + + parent::redirect($url); + } + + /**#@+ + * @author Davey Shafik + * @param int $http_code HTTP Code to check + * @access public + */ + + /** + * Return HTTP Status Code Type + * + * @return int|false + */ + function getStatusType($http_code) + { + if(is_int($http_code) && defined('HTTP_HEADER_STATUS_' .$http_code) || defined($http_code)) { + $type = substr($http_code,0,1); + switch ($type) { + case HTTP_HEADER_STATUS_INFORMATIONAL: + case HTTP_HEADER_STATUS_SUCCESSFUL: + case HTTP_HEADER_STATUS_REDIRECT: + case HTTP_HEADER_STATUS_CLIENT_ERROR: + case HTTP_HEADER_STATUS_SERVER_ERROR: + return $type; + break; + default: + return false; + break; + } + } else { + return false; + } + } + + /** + * Return Status Code Message + * + * @return string|false + */ + function getStatusText($http_code) + { + if ($this->getStatusType($http_code)) { + if (is_int($http_code) && defined('HTTP_HEADER_STATUS_' .$http_code)) { + return substr(constant('HTTP_HEADER_STATUS_' .$http_code),4); + } else { + return substr($http_code,4); + } + } else { + return false; + } + } + + /** + * Checks if HTTP Status code is Information (1xx) + * + * @return boolean + */ + function isInformational($http_code) + { + if ($status_type = $this->getStatusType($http_code)) { + return $status_type{0} == HTTP_HEADER_STATUS_INFORMATIONAL; + } else { + return false; + } + } + + /** + * Checks if HTTP Status code is Successful (2xx) + * + * @return boolean + */ + function isSuccessful($http_code) + { + if ($status_type = $this->getStatusType($http_code)) { + return $status_type{0} == HTTP_HEADER_STATUS_SUCCESSFUL; + } else { + return false; + } + } + + /** + * Checks if HTTP Status code is a Redirect (3xx) + * + * @return boolean + */ + function isRedirect($http_code) + { + if ($status_type = $this->getStatusType($http_code)) { + return $status_type{0} == HTTP_HEADER_STATUS_REDIRECT; + } else { + return false; + } + } + + /** + * Checks if HTTP Status code is a Client Error (4xx) + * + * @return boolean + */ + function isClientError($http_code) + { + if ($status_type = $this->getStatusType($http_code)) { + return $status_type{0} == HTTP_HEADER_STATUS_CLIENT_ERROR; + } else { + return false; + } + } + + /** + * Checks if HTTP Status code is Server Error (5xx) + * + * @return boolean + */ + function isServerError($http_code) + { + if ($status_type = $this->getStatusType($http_code)) { + return $status_type{0} == HTTP_HEADER_STATUS_SERVER_ERROR; + } else { + return false; + } + } + + /** + * Checks if HTTP Status code is Server OR Client Error (4xx or 5xx) + * + * @return boolean + */ + function isError($http_code) + { + if ($status_type = $this->getStatusType($http_code)) { + return (($status_type == HTTP_HEADER_STATUS_CLIENT_ERROR) || ($status_type == HTTP_HEADER_STATUS_SERVER_ERROR)) ? true : false; + } else { + return false; + } + } + /**#@-*/ +} +?> diff --git a/common/PEAR/HTTP/Header/Cache.php b/common/PEAR/HTTP/Header/Cache.php new file mode 100644 index 0000000..af26b76 --- /dev/null +++ b/common/PEAR/HTTP/Header/Cache.php @@ -0,0 +1,238 @@ + + * @author Michael Wallner + * @copyright 2003-2005 The Authors + * @license BSD, revised + * @version CVS: $Id: Cache.php,v 1.24 2005/11/08 19:06:14 mike Exp $ + * @link http://pear.php.net/package/HTTP_Header + */ + +/** + * Requires HTTP_Header + */ +require_once 'HTTP/Header.php'; + +/** + * HTTP_Header_Cache + * + * This package provides methods to easier handle caching of HTTP pages. That + * means that the pages can be cached at the client (user agent or browser) and + * your application only needs to send "hey client you already have the pages". + * + * Which is done by sending the HTTP-Status "304 Not Modified", so that your + * application load and the network traffic can be reduced, since you only need + * to send the complete page once. This is really an advantage e.g. for + * generated style sheets, or simply pages that do only change rarely. + * + * Usage: + * + * require_once 'HTTP/Header/Cache.php'; + * $httpCache = new HTTP_Header_Cache(4, 'weeks'); + * $httpCache->sendHeaders(); + * // your code goes here + * + * + * @package HTTP_Header + * @category HTTP + * @access public + * @version $Revision: 1.24 $ + */ +class HTTP_Header_Cache extends HTTP_Header +{ + /** + * Constructor + * + * Set the amount of time to cache. + * + * @access public + * @return object HTTP_Header_Cache + * @param int $expires + * @param string $unit + */ + function HTTP_Header_Cache($expires = 0, $unit = 'seconds') + { + parent::HTTP_Header(); + $this->setHeader('Pragma', 'cache'); + $this->setHeader('Last-Modified', $this->getCacheStart()); + $this->setHeader('Cache-Control', 'private, must-revalidate, max-age=0'); + + if ($expires) { + if (!$this->isOlderThan($expires, $unit)) { + $this->exitCached(); + } + $this->setHeader('Last-Modified', time()); + } + } + + /** + * Get Cache Start + * + * Returns the unix timestamp of the If-Modified-Since HTTP header or the + * current time if the header was not sent by the client. + * + * @access public + * @return int unix timestamp + */ + function getCacheStart() + { + if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && !$this->isPost()) { + return strtotime(current($array = explode(';', + $_SERVER['HTTP_IF_MODIFIED_SINCE']))); + } + return time(); + } + + /** + * Is Older Than + * + * You can call it like this: + * + * $httpCache->isOlderThan(1, 'day'); + * $httpCache->isOlderThan(47, 'days'); + * + * $httpCache->isOlderThan(1, 'week'); + * $httpCache->isOlderThan(3, 'weeks'); + * + * $httpCache->isOlderThan(1, 'hour'); + * $httpCache->isOlderThan(5, 'hours'); + * + * $httpCache->isOlderThan(1, 'minute'); + * $httpCache->isOlderThan(15, 'minutes'); + * + * $httpCache->isOlderThan(1, 'second'); + * $httpCache->isOlderThan(15); + * + * + * If you specify something greater than "weeks" as time untit, it just + * works approximatly, because a month is taken to consist of 4.3 weeks. + * + * @access public + * @return bool Returns true if requested page is older than specified. + * @param int $time The amount of time. + * @param string $unit The unit of the time amount - (year[s], month[s], + * week[s], day[s], hour[s], minute[s], second[s]). + */ + function isOlderThan($time = 0, $unit = 'seconds') + { + if (!isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || $this->isPost()) { + return true; + } + if (!$time) { + return false; + } + + switch (strtolower($unit)) + { + case 'year': + case 'years': + $time *= 12; + case 'month': + case 'months': + $time *= 4.3; + case 'week': + case 'weeks': + $time *= 7; + case 'day': + case 'days': + $time *= 24; + case 'hour': + case 'hours': + $time *= 60; + case 'minute': + case 'minutes': + $time *= 60; + } + + return (time() - $this->getCacheStart()) > $time; + } + + /** + * Is Cached + * + * Check whether we can consider to be cached on the client side. + * + * @access public + * @return bool Whether the page/resource is considered to be cached. + * @param int $lastModified Unix timestamp of last modification. + */ + function isCached($lastModified = 0) + { + if ($this->isPost()) { + return false; + } + if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && !$lastModified) { + return true; + } + if (!$seconds = time() - $lastModified) { + return false; + } + return !$this->isOlderThan($seconds); + } + + /** + * Is Post + * + * Check if request method is "POST". + * + * @access public + * @return bool + */ + function isPost() + { + return isset($_SERVER['REQUEST_METHOD']) and + 'POST' == $_SERVER['REQUEST_METHOD']; + } + + /** + * Exit If Cached + * + * Exit with "HTTP 304 Not Modified" if we consider to be cached. + * + * @access public + * @return void + * @param int $lastModified Unix timestamp of last modification. + */ + function exitIfCached($lastModified = 0) + { + if ($this->isCached($lastModified)) { + $this->exitCached(); + } + } + + /** + * Exit Cached + * + * Exit with "HTTP 304 Not Modified". + * + * @access public + * @return void + */ + function exitCached() + { + $this->sendHeaders(); + $this->sendStatusCode(304); + exit; + } + + /** + * Set Last Modified + * + * @access public + * @return void + * @param int $lastModified The unix timestamp of last modification. + */ + function setLastModified($lastModified = null) + { + $this->setHeader('Last-Modified', $lastModified); + } +} +?> diff --git a/common/PEAR/HTTP/Upload.php b/common/PEAR/HTTP/Upload.php new file mode 100644 index 0000000..2737d39 --- /dev/null +++ b/common/PEAR/HTTP/Upload.php @@ -0,0 +1,856 @@ + http://www.gnu.org/copyleft/lesser.txt +// (c) 2001-2004 by Tomas Von Veschler Cox +// +// ********************************************** +// +// $Id: Upload.php,v 1.42 2004/08/08 09:37:50 wenz Exp $ + +/* + * Pear File Uploader class. Easy and secure managment of files + * submitted via HTML Forms. + * + * Leyend: + * - you can add error msgs in your language in the HTTP_Upload_Error class + * + * TODO: + * - try to think a way of having all the Error system in other + * file and only include it when an error ocurrs + * + * -- Notes for users HTTP_Upload >= 0.9.0 -- + * + * Error detection was enhanced, so you no longer need to + * check for PEAR::isError() in $upload->getFiles() or call + * $upload->isMissing(). Instead you'll + * get the error when do a check for $file->isError(). + * + * Example: + * + * $upload = new HTTP_Upload('en'); + * $file = $upload->getFiles('i_dont_exist_in_form_definition'); + * if ($file->isError()) { + * die($file->getMessage()); + * } + * + * -- + * + */ + +require_once 'PEAR.php'; + +/** + * defines default chmod + */ +define('HTTP_UPLOAD_DEFAULT_CHMOD', 0660); + +/** + * Error Class for HTTP_Upload + * + * @author Tomas V.V.Cox + * @see http://vulcanonet.com/soft/index.php?pack=uploader + * @package HTTP_Upload + * @category HTTP + * @access public + */ +class HTTP_Upload_Error extends PEAR +{ + /** + * Selected language for error messages + * @var string + */ + var $lang = 'en'; + + /** + * Whether HTML entities shall be encoded automatically + * @var boolean + */ + var $html = false; + + /** + * Constructor + * + * Creates a new PEAR_Error + * + * @param string $lang The language selected for error code messages + * @access public + */ + function HTTP_Upload_Error($lang = null, $html = false) + { + $this->lang = ($lang !== null) ? $lang : $this->lang; + $this->html = ($html !== false) ? $html : $this->html; + $ini_size = preg_replace('/m/i', '000000', ini_get('upload_max_filesize')); + + if (function_exists('version_compare') && + version_compare(phpversion(), '4.1', 'ge')) { + $maxsize = (isset($_POST['MAX_FILE_SIZE'])) ? + $_POST['MAX_FILE_SIZE'] : null; + } else { + global $HTTP_POST_VARS; + $maxsize = (isset($HTTP_POST_VARS['MAX_FILE_SIZE'])) ? + $HTTP_POST_VARS['MAX_FILE_SIZE'] : null; + } + + if (empty($maxsize) || ($maxsize > $ini_size)) { + $maxsize = $ini_size; + } + // XXXXX Add here error messages in your language + $this->error_codes = array( + 'TOO_LARGE' => array( + 'es' => "Fichero demasiado largo. El maximo permitido es: $maxsize bytes.", + 'en' => "File size too large. The maximum permitted size is: $maxsize bytes.", + 'de' => "Datei zu groß. Die zulässige Maximalgröße ist: $maxsize Bytes.", + 'nl' => "Het bestand is te groot, de maximale grootte is: $maxsize bytes.", + 'fr' => "Le fichier est trop gros. La taille maximum autorisée est: $maxsize bytes.", + 'it' => "Il file é troppo grande. Il massimo permesso é: $maxsize bytes.", + 'pt_BR' => "Arquivo muito grande. O tamanho máximo permitido é $maxsize bytes." + ), + 'MISSING_DIR' => array( + 'es' => 'Falta directorio destino.', + 'en' => 'Missing destination directory.', + 'de' => 'Kein Zielverzeichnis definiert.', + 'nl' => 'Geen bestemmings directory.', + 'fr' => 'Le répertoire de destination n\'est pas défini.', + 'it' => 'Manca la directory di destinazione.', + 'pt_BR' => 'Ausência de diretório de destino.' + ), + 'IS_NOT_DIR' => array( + 'es' => 'El directorio destino no existe o es un fichero regular.', + 'en' => 'The destination directory doesn\'t exist or is a regular file.', + 'de' => 'Das angebene Zielverzeichnis existiert nicht oder ist eine Datei.', + 'nl' => 'De doeldirectory bestaat niet, of is een gewoon bestand.', + 'fr' => 'Le répertoire de destination n\'existe pas ou il s\'agit d\'un fichier régulier.', + 'it' => 'La directory di destinazione non esiste o é un file.', + 'pt_BR' => 'O diretório de destino não existe ou é um arquivo.' + ), + 'NO_WRITE_PERMS' => array( + 'es' => 'El directorio destino no tiene permisos de escritura.', + 'en' => 'The destination directory doesn\'t have write perms.', + 'de' => 'Fehlende Schreibrechte für das Zielverzeichnis.', + 'nl' => 'Geen toestemming om te schrijven in de doeldirectory.', + 'fr' => 'Le répertoire de destination n\'a pas les droits en écriture.', + 'it' => 'Non si hanno i permessi di scrittura sulla directory di destinazione.', + 'pt_BR' => 'O diretório de destino não possui permissão para escrita.' + ), + 'NO_USER_FILE' => array( + 'es' => 'No se ha escogido fichero para el upload.', + 'en' => 'You haven\'t selected any file for uploading.', + 'de' => 'Es wurde keine Datei für den Upload ausgewählt.', + 'nl' => 'Er is geen bestand opgegeven om te uploaden.', + 'fr' => 'Vous n\'avez pas sélectionné de fichier à envoyer.', + 'it' => 'Nessun file selezionato per l\'upload.', + 'pt_BR' => 'Nenhum arquivo selecionado para upload.' + ), + 'BAD_FORM' => array( + 'es' => 'El formulario no contiene method="post" enctype="multipart/form-data" requerido.', + 'en' => 'The html form doesn\'t contain the required method="post" enctype="multipart/form-data".', + 'de' => 'Das HTML-Formular enthält nicht die Angabe method="post" enctype="multipart/form-data" '. + 'im >form<-Tag.', + 'nl' => 'Het HTML-formulier bevat niet de volgende benodigde '. + 'eigenschappen: method="post" enctype="multipart/form-data".', + 'fr' => 'Le formulaire HTML ne contient pas les attributs requis : '. + ' method="post" enctype="multipart/form-data".', + 'it' => 'Il modulo HTML non contiene gli attributi richiesti: "'. + ' method="post" enctype="multipart/form-data".', + 'pt_BR' => 'O formulário HTML não possui o method="post" enctype="multipart/form-data" requerido.' + ), + 'E_FAIL_COPY' => array( + 'es' => 'Fallo al copiar el fichero temporal.', + 'en' => 'Failed to copy the temporary file.', + 'de' => 'Temporäre Datei konnte nicht kopiert werden.', + 'nl' => 'Het tijdelijke bestand kon niet gekopieerd worden.', + 'fr' => 'L\'enregistrement du fichier temporaire a échoué.', + 'it' => 'Copia del file temporaneo fallita.', + 'pt_BR' => 'Falha ao copiar o arquivo temporário.' + ), + 'E_FAIL_MOVE' => array( + 'es' => 'No puedo mover el fichero.', + 'en' => 'Impossible to move the file.', + 'de' => 'Datei kann nicht verschoben werden.', + 'nl' => 'Het bestand kon niet verplaatst worden.', + 'fr' => 'Impossible de déplacer le fichier.', + 'pt_BR' => 'Não foi possível mover o arquivo.' + ), + 'FILE_EXISTS' => array( + 'es' => 'El fichero destino ya existe.', + 'en' => 'The destination file already exists.', + 'de' => 'Die zu erzeugende Datei existiert bereits.', + 'nl' => 'Het doelbestand bestaat al.', + 'fr' => 'Le fichier de destination existe déjà.', + 'it' => 'File destinazione già esistente.', + 'pt_BR' => 'O arquivo de destino já existe.' + ), + 'CANNOT_OVERWRITE' => array( + 'es' => 'El fichero destino ya existe y no se puede sobreescribir.', + 'en' => 'The destination file already exists and could not be overwritten.', + 'de' => 'Die zu erzeugende Datei existiert bereits und konnte nicht überschrieben werden.', + 'nl' => 'Het doelbestand bestaat al, en kon niet worden overschreven.', + 'fr' => 'Le fichier de destination existe déjà et ne peux pas être remplacé.', + 'it' => 'File destinazione già esistente e non si può sovrascrivere.', + 'pt_BR' => 'O arquivo de destino já existe e não pôde ser sobrescrito.' + ), + 'NOT_ALLOWED_EXTENSION' => array( + 'es' => 'Extension de fichero no permitida.', + 'en' => 'File extension not permitted.', + 'de' => 'Unerlaubte Dateiendung.', + 'nl' => 'Niet toegestane bestands-extensie.', + 'fr' => 'Le fichier a une extension non autorisée.', + 'it' => 'Estensione del File non permessa.', + 'pt_BR' => 'Extensão de arquivo não permitida.' + ), + 'PARTIAL' => array( + 'es' => 'El fichero fue parcialmente subido', + 'en' => 'The file was only partially uploaded.', + 'de' => 'Die Datei wurde unvollständig übertragen.', + 'nl' => 'Het bestand is slechts gedeeltelijk geupload.', + 'pt_BR' => 'O arquivo no foi enviado por completo.' + ), + 'ERROR' => array( + 'es' => 'Error en subida:', + 'en' => 'Upload error:', + 'de' => 'Fehler beim Upload:', + 'nl' => 'Upload fout:', + 'pt_BR' => 'Erro de upload:' + ), + 'DEV_NO_DEF_FILE' => array( + 'es' => 'No est definido en el formulario este nombre de fichero como <input type="file" name=?>.', + 'en' => 'This filename is not defined in the form as <input type="file" name=?>.', + 'de' => 'Dieser Dateiname ist im Formular nicht als <input type="file" name=?> definiert.', + 'nl' => 'Deze bestandsnaam is niett gedefineerd in het formulier als <input type="file" name=?>.' + ) + ); + } + + /** + * returns the error code + * + * @param string $e_code type of error + * @return string Error message + */ + function errorCode($e_code) + { + if (!empty($this->error_codes[$e_code][$this->lang])) { + $msg = $this->html ? + html_entity_decode($this->error_codes[$e_code][$this->lang]) : + $this->error_codes[$e_code][$this->lang]; + } else { + $msg = $e_code; + } + + if (!empty($this->error_codes['ERROR'][$this->lang])) { + $error = $this->error_codes['ERROR'][$this->lang]; + } else { + $error = $this->error_codes['ERROR']['en']; + } + return $error.' '.$msg; + } + + /** + * Overwrites the PEAR::raiseError method + * + * @param string $e_code type of error + * @return object PEAR_Error a PEAR-Error object + * @access public + */ + function raiseError($e_code) + { + return PEAR::raiseError($this->errorCode($e_code), $e_code); + } +} + +/** + * This class provides an advanced file uploader system + * for file uploads made from html forms + + * + * @author Tomas V.V.Cox + * @see http://vulcanonet.com/soft/index.php?pack=uploader + * @package HTTP_Upload + * @category HTTP + * @access public + */ +class HTTP_Upload extends HTTP_Upload_Error +{ + /** + * Contains an array of "uploaded files" objects + * @var array + */ + var $files = array(); + + /** + * Contains the desired chmod for uploaded files + * @var int + * @access private + */ + var $_chmod = HTTP_UPLOAD_DEFAULT_CHMOD; + + /** + * Constructor + * + * @param string $lang Language to use for reporting errors + * @see Upload_Error::error_codes + * @access public + */ + function HTTP_Upload($lang = null) + { + $this->HTTP_Upload_Error($lang); + if (function_exists('version_compare') && + version_compare(phpversion(), '4.1', 'ge')) + { + $this->post_files = $_FILES; + if (isset($_SERVER['CONTENT_TYPE'])) { + $this->content_type = $_SERVER['CONTENT_TYPE']; + } + } else { + global $HTTP_POST_FILES, $HTTP_SERVER_VARS; + $this->post_files = $HTTP_POST_FILES; + if (isset($HTTP_SERVER_VARS['CONTENT_TYPE'])) { + $this->content_type = $HTTP_SERVER_VARS['CONTENT_TYPE']; + } + } + } + + /** + * Get files + * + * @param mixed $file If: + * - not given, function will return array of upload_file objects + * - is int, will return the $file position in upload_file objects array + * - is string, will return the upload_file object corresponding + * to $file name of the form. For ex: + * if form is + * to get this file use: $upload->getFiles('userfile') + * + * @return mixed array or object (see @param $file above) or Pear_Error + * @access public + */ + function &getFiles($file = null) + { + static $is_built = false; + //build only once for multiple calls + if (!$is_built) { + $files = &$this->_buildFiles(); + if (PEAR::isError($files)) { + // there was an error with the form. + // Create a faked upload embedding the error + $this->files['_error'] = &new HTTP_Upload_File( + '_error', null, + null, null, + null, $files->getCode(), + $this->lang, $this->_chmod); + } else { + $this->files = $files; + } + $is_built = true; + } + if ($file !== null) { + if (is_int($file)) { + $pos = 0; + foreach ($this->files as $obj) { + if ($pos == $file) { + return $obj; + } + $pos++; + } + } elseif (is_string($file) && isset($this->files[$file])) { + return $this->files[$file]; + } + if (isset($this->files['_error'])) { + return $this->files['_error']; + } else { + // developer didn't specify this name in the form + // warn him about it with a faked upload + return new HTTP_Upload_File( + '_error', null, + null, null, + null, 'DEV_NO_DEF_FILE', + $this->lang); + } + } + return $this->files; + } + + /** + * Creates the list of the uploaded file + * + * @return array of HTTP_Upload_File objects for every file + */ + function &_buildFiles() + { + // Form method check + if (!isset($this->content_type) || + strpos($this->content_type, 'multipart/form-data') !== 0) + { + return $this->raiseError('BAD_FORM'); + } + // In 4.1 $_FILES isn't initialized when no uploads + // XXX (cox) afaik, in >= 4.1 and <= 4.3 only + if (function_exists('version_compare') && + version_compare(phpversion(), '4.1', 'ge')) + { + $error = $this->isMissing(); + if (PEAR::isError($error)) { + return $error; + } + } + + // map error codes from 4.2.0 $_FILES['userfile']['error'] + if (function_exists('version_compare') && + version_compare(phpversion(), '4.2.0', 'ge')) { + $uploadError = array( + 1 => 'TOO_LARGE', + 2 => 'TOO_LARGE', + 3 => 'PARTIAL', + 4 => 'NO_USER_FILE' + ); + } + + + // Parse $_FILES (or $HTTP_POST_FILES) + $files = array(); + foreach ($this->post_files as $userfile => $value) { + if (is_array($value['name'])) { + foreach ($value['name'] as $key => $val) { + $err = $value['error'][$key]; + if (isset($err) && $err !== 0 && isset($uploadError[$err])) { + $error = $uploadError[$err]; + } else { + $error = null; + } + $name = basename($value['name'][$key]); + $tmp_name = $value['tmp_name'][$key]; + $size = $value['size'][$key]; + $type = $value['type'][$key]; + $formname = $userfile . "[$key]"; + $files[$formname] = new HTTP_Upload_File($name, $tmp_name, + $formname, $type, $size, $error, $this->lang, $this->_chmod); + } + // One file + } else { + $err = $value['error']; + if (isset($err) && $err !== 0 && isset($uploadError[$err])) { + $error = $uploadError[$err]; + } else { + $error = null; + } + $name = basename($value['name']); + $tmp_name = $value['tmp_name']; + $size = $value['size']; + $type = $value['type']; + $formname = $userfile; + $files[$formname] = new HTTP_Upload_File($name, $tmp_name, + $formname, $type, $size, $error, $this->lang, $this->_chmod); + } + } + return $files; + } + + /** + * Checks if the user submited or not some file + * + * @return mixed False when are files or PEAR_Error when no files + * @access public + * @see Read the note in the source code about this function + */ + function isMissing() + { + if (count($this->post_files) < 1) { + return $this->raiseError('NO_USER_FILE'); + } + //we also check if at least one file has more than 0 bytes :) + $files = array(); + $size = 0; + foreach ($this->post_files as $userfile => $value) { + if (is_array($value['name'])) { + foreach ($value['name'] as $key => $val) { + $size += $value['size'][$key]; + } + } else { //one file + $size = $value['size']; + } + } + if ($size == 0) { + $this->raiseError('NO_USER_FILE'); + } + return false; + } + + /** + * Sets the chmod to be used for uploaded files + * + * @param int Desired mode + */ + function setChmod($mode) + { + $this->_chmod = $mode; + } +} + +/** + * This class provides functions to work with the uploaded file + * + * @author Tomas V.V.Cox + * @see http://vulcanonet.com/soft/index.php?pack=uploader + * @package HTTP_Upload + * @category HTTP + * @access public + */ +class HTTP_Upload_File extends HTTP_Upload_Error +{ + /** + * If the random seed was initialized before or not + * @var boolean; + */ + var $_seeded = 0; + + /** + * Assoc array with file properties + * @var array + */ + var $upload = array(); + + /** + * If user haven't selected a mode, by default 'safe' will be used + * @var boolean + */ + var $mode_name_selected = false; + + /** + * It's a common security risk in pages who has the upload dir + * under the document root (remember the hack of the Apache web?) + * + * @var array + * @access private + * @see HTTP_Upload_File::setValidExtensions() + */ + var $_extensions_check = array('php', 'phtm', 'phtml', 'php3', 'inc'); + + /** + * @see HTTP_Upload_File::setValidExtensions() + * @var string + * @access private + */ + var $_extensions_mode = 'deny'; + + /** + * Contains the desired chmod for uploaded files + * @var int + * @access private + */ + var $_chmod = HTTP_UPLOAD_DEFAULT_CHMOD; + + /** + * Constructor + * + * @param string $name destination file name + * @param string $tmp temp file name + * @param string $formname name of the form + * @param string $type Mime type of the file + * @param string $size size of the file + * @param string $error error on upload + * @param string $lang used language for errormessages + * @access public + */ + function HTTP_Upload_File($name = null, $tmp = null, $formname = null, + $type = null, $size = null, $error = null, + $lang = null, $chmod = HTTP_UPLOAD_DEFAULT_CHMOD) + { + $this->HTTP_Upload_Error($lang); + $ext = null; + + if (empty($name) || $size == 0) { + $error = 'NO_USER_FILE'; + } elseif ($tmp == 'none') { + $error = 'TOO_LARGE'; + } else { + // strpos needed to detect files without extension + if (($pos = strrpos($name, '.')) !== false) { + $ext = substr($name, $pos + 1); + } + } + + if (function_exists('version_compare') && + version_compare(phpversion(), '4.1', 'ge')) { + if (isset($_POST['MAX_FILE_SIZE']) && + $size > $_POST['MAX_FILE_SIZE']) { + $error = 'TOO_LARGE'; + } + } else { + global $HTTP_POST_VARS; + if (isset($HTTP_POST_VARS['MAX_FILE_SIZE']) && + $size > $HTTP_POST_VARS['MAX_FILE_SIZE']) { + $error = 'TOO_LARGE'; + } + } + + $this->upload = array( + 'real' => $name, + 'name' => $name, + 'form_name' => $formname, + 'ext' => $ext, + 'tmp_name' => $tmp, + 'size' => $size, + 'type' => $type, + 'error' => $error + ); + + $this->_chmod = $chmod; + } + + /** + * Sets the name of the destination file + * + * @param string $mode A valid mode: 'uniq', 'safe' or 'real' or a file name + * @param string $prepend A string to prepend to the name + * @param string $append A string to append to the name + * + * @return string The modified name of the destination file + * @access public + */ + function setName($mode, $prepend = null, $append = null) + { + switch ($mode) { + case 'uniq': + $name = $this->nameToUniq(); + $this->upload['ext'] = $this->nameToSafe($this->upload['ext'], 10); + $name .= '.' . $this->upload['ext']; + break; + case 'safe': + $name = $this->nameToSafe($this->upload['real']); + if (($pos = strrpos($name, '.')) !== false) { + $this->upload['ext'] = substr($name, $pos + 1); + } else { + $this->upload['ext'] = ''; + } + break; + case 'real': + $name = $this->upload['real']; + break; + default: + $name = $mode; + } + $this->upload['name'] = $prepend . $name . $append; + $this->mode_name_selected = true; + return $this->upload['name']; + } + + /** + * Unique file names in the form: 9022210413b75410c28bef.html + * @see HTTP_Upload_File::setName() + */ + function nameToUniq() + { + if (! $this->_seeded) { + srand((double) microtime() * 1000000); + $this->_seeded = 1; + } + $uniq = uniqid(rand()); + return $uniq; + } + + /** + * Format a file name to be safe + * + * @param string $file The string file name + * @param int $maxlen Maximun permited string lenght + * @return string Formatted file name + * @see HTTP_Upload_File::setName() + */ + function nameToSafe($name, $maxlen=250) + { + $noalpha = '@'; + $alpha = 'AEIOUYaeiouyAEIOUaeiouAEIOUaeiouAEIOUaeiouyAaOoAaNnCcaooa'; + + $name = substr($name, 0, $maxlen); + $name = strtr($name, $noalpha, $alpha); + // not permitted chars are replaced with "_" + return preg_replace('/[^a-zA-Z0-9,._\+\()\-]/', '_', $name); + } + + /** + * The upload was valid + * + * @return bool If the file was submitted correctly + * @access public + */ + function isValid() + { + if ($this->upload['error'] === null) { + return true; + } + return false; + } + + /** + * User haven't submit a file + * + * @return bool If the user submitted a file or not + * @access public + */ + function isMissing() + { + if ($this->upload['error'] == 'NO_USER_FILE') { + return true; + } + return false; + } + + /** + * Some error occured during upload (most common due a file size problem, + * like max size exceeded or 0 bytes long). + * @return bool If there were errors submitting the file (probably + * because the file excess the max permitted file size) + * @access public + */ + function isError() + { + if (in_array($this->upload['error'], array('TOO_LARGE', 'BAD_FORM','DEV_NO_DEF_FILE'))) { + return true; + } + return false; + } + + /** + * Moves the uploaded file to its destination directory. + * + * @param string $dir_dest Destination directory + * @param bool $overwrite Overwrite if destination file exists? + * @return mixed True on success or Pear_Error object on error + * @access public + */ + function moveTo($dir_dest, $overwrite = true) + { + if (!$this->isValid()) { + return $this->raiseError($this->upload['error']); + } + + //Valid extensions check + if (!$this->_evalValidExtensions()) { + return $this->raiseError('NOT_ALLOWED_EXTENSION'); + } + + $err_code = $this->_chk_dir_dest($dir_dest); + if ($err_code !== false) { + return $this->raiseError($err_code); + } + // Use 'safe' mode by default if no other was selected + if (!$this->mode_name_selected) { + $this->setName('safe'); + } + + $name_dest = $dir_dest . DIRECTORY_SEPARATOR . $this->upload['name']; + + if (@is_file($name_dest)) { + if ($overwrite !== true) { + return $this->raiseError('FILE_EXISTS'); + } elseif (!is_writable($name_dest)) { + return $this->raiseError('CANNOT_OVERWRITE'); + } + } + + // copy the file and let php clean the tmp + if (!@move_uploaded_file($this->upload['tmp_name'], $name_dest)) { + return $this->raiseError('E_FAIL_MOVE'); + } + @chmod($name_dest, $this->_chmod); + return $this->getProp('name'); + } + + /** + * Check for a valid destination dir + * + * @param string $dir_dest Destination dir + * @return mixed False on no errors or error code on error + */ + function _chk_dir_dest($dir_dest) + { + if (!$dir_dest) { + return 'MISSING_DIR'; + } + if (!@is_dir ($dir_dest)) { + return 'IS_NOT_DIR'; + } + if (!is_writeable ($dir_dest)) { + return 'NO_WRITE_PERMS'; + } + return false; + } + /** + * Retrive properties of the uploaded file + * @param string $name The property name. When null an assoc array with + * all the properties will be returned + * @return mixed A string or array + * @see HTTP_Upload_File::HTTP_Upload_File() + * @access public + */ + function getProp($name = null) + { + if ($name === null) { + return $this->upload; + } + return $this->upload[$name]; + } + + /** + * Returns a error message, if a error occured + * (deprecated) Use getMessage() instead + * @return string a Error message + * @access public + */ + function errorMsg() + { + return $this->errorCode($this->upload['error']); + } + + /** + * Returns a error message, if a error occured + * @return string a Error message + * @access public + */ + function getMessage() + { + return $this->errorCode($this->upload['error']); + } + + /** + * Function to restrict the valid extensions on file uploads + * + * @param array $exts File extensions to validate + * @param string $mode The type of validation: + * 1) 'deny' Will deny only the supplied extensions + * 2) 'accept' Will accept only the supplied extensions + * as valid + * @access public + */ + function setValidExtensions($exts, $mode = 'deny') + { + $this->_extensions_check = $exts; + $this->_extensions_mode = $mode; + } + + /** + * Evaluates the validity of the extensions set by setValidExtensions + * + * @return bool False on non valid extension, true if they are valid + * @access private + */ + function _evalValidExtensions() + { + $exts = $this->_extensions_check; + settype($exts, 'array'); + if ($this->_extensions_mode == 'deny') { + if (in_array($this->getProp('ext'), $exts)) { + return false; + } + // mode == 'accept' + } else { + if (!in_array($this->getProp('ext'), $exts)) { + return false; + } + } + return true; + } +} +?> \ No newline at end of file diff --git a/common/PEAR/Mail.php b/common/PEAR/Mail.php new file mode 100644 index 0000000..977314c --- /dev/null +++ b/common/PEAR/Mail.php @@ -0,0 +1,194 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Mail.php,v 1.6 2003/06/26 07:05:36 jon Exp $ + +require_once 'PEAR.php'; + +/** + * PEAR's Mail:: interface. Defines the interface for implementing + * mailers under the PEAR hierarchy, and provides supporting functions + * useful in multiple mailer backends. + * + * @access public + * @version $Revision: 1.6 $ + * @package Mail + */ +class Mail +{ + /** + * Line terminator used for separating header lines. + * @var string + */ + var $sep = "\r\n"; + + /** + * Provides an interface for generating Mail:: objects of various + * types + * + * @param string $driver The kind of Mail:: object to instantiate. + * @param array $params The parameters to pass to the Mail:: object. + * @return object Mail a instance of the driver class or if fails a PEAR Error + * @access public + */ + function factory($driver, $params = array()) + { + $driver = strtolower($driver); + @include_once 'Mail/' . $driver . '.php'; + $class = 'Mail_' . $driver; + if (class_exists($class)) { + return new $class($params); + } else { + return PEAR::raiseError('Unable to find class for driver ' . $driver); + } + } + + /** + * Implements Mail::send() function using php's built-in mail() + * command. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * @access public + * @deprecated use Mail_mail::send instead + */ + function send($recipients, $headers, $body) + { + // if we're passed an array of recipients, implode it. + if (is_array($recipients)) { + $recipients = implode(', ', $recipients); + } + + // get the Subject out of the headers array so that we can + // pass it as a seperate argument to mail(). + $subject = ''; + if (isset($headers['Subject'])) { + $subject = $headers['Subject']; + unset($headers['Subject']); + } + + // flatten the headers out. + list(,$text_headers) = Mail::prepareHeaders($headers); + + return mail($recipients, $subject, $body, $text_headers); + + } + + /** + * Take an array of mail headers and return a string containing + * text usable in sending a message. + * + * @param array $headers The array of headers to prepare, in an associative + * array, where the array key is the header name (ie, + * 'Subject'), and the array value is the header + * value (ie, 'test'). The header produced from those + * values would be 'Subject: test'. + * + * @return mixed Returns false if it encounters a bad address, + * otherwise returns an array containing two + * elements: Any From: address found in the headers, + * and the plain text version of the headers. + * @access private + */ + function prepareHeaders($headers) + { + $lines = array(); + $from = null; + + foreach ($headers as $key => $value) { + if ($key === 'From') { + include_once 'Mail/RFC822.php'; + + $addresses = Mail_RFC822::parseAddressList($value, 'localhost', + false); + $from = $addresses[0]->mailbox . '@' . $addresses[0]->host; + + // Reject envelope From: addresses with spaces. + if (strstr($from, ' ')) { + return false; + } + + $lines[] = $key . ': ' . $value; + } elseif ($key === 'Received') { + // Put Received: headers at the top. Spam detectors often + // flag messages with Received: headers after the Subject: + // as spam. + array_unshift($lines, $key . ': ' . $value); + } else { + $lines[] = $key . ': ' . $value; + } + } + + return array($from, join($this->sep, $lines) . $this->sep); + } + + /** + * Take a set of recipients and parse them, returning an array of + * bare addresses (forward paths) that can be passed to sendmail + * or an smtp server with the rcpt to: command. + * + * @param mixed Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. + * + * @return array An array of forward paths (bare addresses). + * @access private + */ + function parseRecipients($recipients) + { + include_once 'Mail/RFC822.php'; + + // if we're passed an array, assume addresses are valid and + // implode them before parsing. + if (is_array($recipients)) { + $recipients = implode(', ', $recipients); + } + + // Parse recipients, leaving out all personal info. This is + // for smtp recipients, etc. All relevant personal information + // should already be in the headers. + $addresses = Mail_RFC822::parseAddressList($recipients, 'localhost', false); + $recipients = array(); + if (is_array($addresses)) { + foreach ($addresses as $ob) { + $recipients[] = $ob->mailbox . '@' . $ob->host; + } + } + + return $recipients; + } + +} +?> diff --git a/common/PEAR/Mail/RFC822.php b/common/PEAR/Mail/RFC822.php new file mode 100644 index 0000000..0a82618 --- /dev/null +++ b/common/PEAR/Mail/RFC822.php @@ -0,0 +1,916 @@ + | +// | Chuck Hagenbuch | +// +-----------------------------------------------------------------------+ + +/** +* RFC 822 Email address list validation Utility +* +* What is it? +* +* This class will take an address string, and parse it into it's consituent +* parts, be that either addresses, groups, or combinations. Nested groups +* are not supported. The structure it returns is pretty straight forward, +* and is similar to that provided by the imap_rfc822_parse_adrlist(). Use +* print_r() to view the structure. +* +* How do I use it? +* +* $address_string = 'My Group: "Richard" (A comment), ted@example.com (Ted Bloggs), Barney;'; +* $structure = Mail_RFC822::parseAddressList($address_string, 'example.com', true) +* print_r($structure); +* +* @author Richard Heyes +* @author Chuck Hagenbuch +* @version $Revision: 1.12 $ +* @license BSD +* @package Mail +*/ + +class Mail_RFC822 { + + /** + * The address being parsed by the RFC822 object. + * @var string $address + */ + var $address = ''; + + /** + * The default domain to use for unqualified addresses. + * @var string $default_domain + */ + var $default_domain = 'localhost'; + + /** + * Should we return a nested array showing groups, or flatten everything? + * @var boolean $nestGroups + */ + var $nestGroups = true; + + /** + * Whether or not to validate atoms for non-ascii characters. + * @var boolean $validate + */ + var $validate = true; + + /** + * The array of raw addresses built up as we parse. + * @var array $addresses + */ + var $addresses = array(); + + /** + * The final array of parsed address information that we build up. + * @var array $structure + */ + var $structure = array(); + + /** + * The current error message, if any. + * @var string $error + */ + var $error = null; + + /** + * An internal counter/pointer. + * @var integer $index + */ + var $index = null; + + /** + * The number of groups that have been found in the address list. + * @var integer $num_groups + * @access public + */ + var $num_groups = 0; + + /** + * A variable so that we can tell whether or not we're inside a + * Mail_RFC822 object. + * @var boolean $mailRFC822 + */ + var $mailRFC822 = true; + + /** + * A limit after which processing stops + * @var int $limit + */ + var $limit = null; + + + /** + * Sets up the object. The address must either be set here or when + * calling parseAddressList(). One or the other. + * + * @access public + * @param string $address The address(es) to validate. + * @param string $default_domain Default domain/host etc. If not supplied, will be set to localhost. + * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. + * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. + * + * @return object Mail_RFC822 A new Mail_RFC822 object. + */ + function Mail_RFC822($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) + { + if (isset($address)) $this->address = $address; + if (isset($default_domain)) $this->default_domain = $default_domain; + if (isset($nest_groups)) $this->nestGroups = $nest_groups; + if (isset($validate)) $this->validate = $validate; + if (isset($limit)) $this->limit = $limit; + } + + + /** + * Starts the whole process. The address must either be set here + * or when creating the object. One or the other. + * + * @access public + * @param string $address The address(es) to validate. + * @param string $default_domain Default domain/host etc. + * @param boolean $nest_groups Whether to return the structure with groups nested for easier viewing. + * @param boolean $validate Whether to validate atoms. Turn this off if you need to run addresses through before encoding the personal names, for instance. + * + * @return array A structured array of addresses. + */ + function parseAddressList($address = null, $default_domain = null, $nest_groups = null, $validate = null, $limit = null) + { + + if (!isset($this->mailRFC822)) { + $obj = new Mail_RFC822($address, $default_domain, $nest_groups, $validate, $limit); + return $obj->parseAddressList(); + } + + if (isset($address)) $this->address = $address; + if (isset($default_domain)) $this->default_domain = $default_domain; + if (isset($nest_groups)) $this->nestGroups = $nest_groups; + if (isset($validate)) $this->validate = $validate; + if (isset($limit)) $this->limit = $limit; + + $this->structure = array(); + $this->addresses = array(); + $this->error = null; + $this->index = null; + + while ($this->address = $this->_splitAddresses($this->address)) { + continue; + } + + if ($this->address === false || isset($this->error)) { + require_once 'PEAR.php'; + return PEAR::raiseError($this->error); + } + + // Loop through all the addresses + for ($i = 0; $i < count($this->addresses); $i++) { + if (($return = $this->_validateAddress($this->addresses[$i])) === false + || isset($this->error)) { + require_once 'PEAR.php'; + return PEAR::raiseError($this->error); + } + + if (!$this->nestGroups) { + $this->structure = array_merge($this->structure, $return); + } else { + $this->structure[] = $return; + } + } + + return $this->structure; + } + + /** + * Splits an address into seperate addresses. + * + * @access private + * @param string $address The addresses to split. + * @return boolean Success or failure. + */ + function _splitAddresses($address) + { + + if (!empty($this->limit) AND count($this->addresses) == $this->limit) { + return ''; + } + + if ($this->_isGroup($address) && !isset($this->error)) { + $split_char = ';'; + $is_group = true; + } elseif (!isset($this->error)) { + $split_char = ','; + $is_group = false; + } elseif (isset($this->error)) { + return false; + } + + // Split the string based on the above ten or so lines. + $parts = explode($split_char, $address); + $string = $this->_splitCheck($parts, $split_char); + + // If a group... + if ($is_group) { + // If $string does not contain a colon outside of + // brackets/quotes etc then something's fubar. + + // First check there's a colon at all: + if (strpos($string, ':') === false) { + $this->error = 'Invalid address: ' . $string; + return false; + } + + // Now check it's outside of brackets/quotes: + if (!$this->_splitCheck(explode(':', $string), ':')) { + return false; + } + + // We must have a group at this point, so increase the counter: + $this->num_groups++; + } + + // $string now contains the first full address/group. + // Add to the addresses array. + $this->addresses[] = array( + 'address' => trim($string), + 'group' => $is_group + ); + + // Remove the now stored address from the initial line, the +1 + // is to account for the explode character. + $address = trim(substr($address, strlen($string) + 1)); + + // If the next char is a comma and this was a group, then + // there are more addresses, otherwise, if there are any more + // chars, then there is another address. + if ($is_group && substr($address, 0, 1) == ','){ + $address = trim(substr($address, 1)); + return $address; + + } elseif (strlen($address) > 0) { + return $address; + + } else { + return ''; + } + + // If you got here then something's off + return false; + } + + /** + * Checks for a group at the start of the string. + * + * @access private + * @param string $address The address to check. + * @return boolean Whether or not there is a group at the start of the string. + */ + function _isGroup($address) + { + // First comma not in quotes, angles or escaped: + $parts = explode(',', $address); + $string = $this->_splitCheck($parts, ','); + + // Now we have the first address, we can reliably check for a + // group by searching for a colon that's not escaped or in + // quotes or angle brackets. + if (count($parts = explode(':', $string)) > 1) { + $string2 = $this->_splitCheck($parts, ':'); + return ($string2 !== $string); + } else { + return false; + } + } + + /** + * A common function that will check an exploded string. + * + * @access private + * @param array $parts The exloded string. + * @param string $char The char that was exploded on. + * @return mixed False if the string contains unclosed quotes/brackets, or the string on success. + */ + function _splitCheck($parts, $char) + { + $string = $parts[0]; + + for ($i = 0; $i < count($parts); $i++) { + if ($this->_hasUnclosedQuotes($string) + || $this->_hasUnclosedBrackets($string, '<>') + || $this->_hasUnclosedBrackets($string, '[]') + || $this->_hasUnclosedBrackets($string, '()') + || substr($string, -1) == '\\') { + if (isset($parts[$i + 1])) { + $string = $string . $char . $parts[$i + 1]; + } else { + $this->error = 'Invalid address spec. Unclosed bracket or quotes'; + return false; + } + } else { + $this->index = $i; + break; + } + } + + return $string; + } + + /** + * Checks if a string has an unclosed quotes or not. + * + * @access private + * @param string $string The string to check. + * @return boolean True if there are unclosed quotes inside the string, false otherwise. + */ + function _hasUnclosedQuotes($string) + { + $string = explode('"', $string); + $string_cnt = count($string); + + for ($i = 0; $i < (count($string) - 1); $i++) + if (substr($string[$i], -1) == '\\') + $string_cnt--; + + return ($string_cnt % 2 === 0); + } + + /** + * Checks if a string has an unclosed brackets or not. IMPORTANT: + * This function handles both angle brackets and square brackets; + * + * @access private + * @param string $string The string to check. + * @param string $chars The characters to check for. + * @return boolean True if there are unclosed brackets inside the string, false otherwise. + */ + function _hasUnclosedBrackets($string, $chars) + { + $num_angle_start = substr_count($string, $chars[0]); + $num_angle_end = substr_count($string, $chars[1]); + + $this->_hasUnclosedBracketsSub($string, $num_angle_start, $chars[0]); + $this->_hasUnclosedBracketsSub($string, $num_angle_end, $chars[1]); + + if ($num_angle_start < $num_angle_end) { + $this->error = 'Invalid address spec. Unmatched quote or bracket (' . $chars . ')'; + return false; + } else { + return ($num_angle_start > $num_angle_end); + } + } + + /** + * Sub function that is used only by hasUnclosedBrackets(). + * + * @access private + * @param string $string The string to check. + * @param integer &$num The number of occurences. + * @param string $char The character to count. + * @return integer The number of occurences of $char in $string, adjusted for backslashes. + */ + function _hasUnclosedBracketsSub($string, &$num, $char) + { + $parts = explode($char, $string); + for ($i = 0; $i < count($parts); $i++){ + if (substr($parts[$i], -1) == '\\' || $this->_hasUnclosedQuotes($parts[$i])) + $num--; + if (isset($parts[$i + 1])) + $parts[$i + 1] = $parts[$i] . $char . $parts[$i + 1]; + } + + return $num; + } + + /** + * Function to begin checking the address. + * + * @access private + * @param string $address The address to validate. + * @return mixed False on failure, or a structured array of address information on success. + */ + function _validateAddress($address) + { + $is_group = false; + $addresses = array(); + + if ($address['group']) { + $is_group = true; + + // Get the group part of the name + $parts = explode(':', $address['address']); + $groupname = $this->_splitCheck($parts, ':'); + $structure = array(); + + // And validate the group part of the name. + if (!$this->_validatePhrase($groupname)){ + $this->error = 'Group name did not validate.'; + return false; + } else { + // Don't include groups if we are not nesting + // them. This avoids returning invalid addresses. + if ($this->nestGroups) { + $structure = new stdClass; + $structure->groupname = $groupname; + } + } + + $address['address'] = ltrim(substr($address['address'], strlen($groupname . ':'))); + } + + // If a group then split on comma and put into an array. + // Otherwise, Just put the whole address in an array. + if ($is_group) { + while (strlen($address['address']) > 0) { + $parts = explode(',', $address['address']); + $addresses[] = $this->_splitCheck($parts, ','); + $address['address'] = trim(substr($address['address'], strlen(end($addresses) . ','))); + } + } else { + $addresses[] = $address['address']; + } + + // Check that $addresses is set, if address like this: + // Groupname:; + // Then errors were appearing. + if (!count($addresses)){ + $this->error = 'Empty group.'; + return false; + } + + // Validate each mailbox. + // Format could be one of: name + // geezer@domain.com + // geezer + // ... or any other format valid by RFC 822. + for ($i = 0; $i < count($addresses); $i++) { + $addresses[$i] = trim($addresses[$i]); + if (!$this->validateMailbox($addresses[$i])) { + if (empty($this->error)) { + $this->error = 'Validation failed for "' . $addresses[$i] . '"'; + } + return false; + } + } + + // Nested format + if ($this->nestGroups) { + if ($is_group) { + $structure->addresses = $addresses; + } else { + $structure = $addresses[0]; + } + + // Flat format + } else { + if ($is_group) { + $structure = array_merge($structure, $addresses); + } else { + $structure = $addresses; + } + } + + return $structure; + } + + /** + * Function to validate a phrase. + * + * @access private + * @param string $phrase The phrase to check. + * @return boolean Success or failure. + */ + function _validatePhrase($phrase) + { + // Splits on one or more Tab or space. + $parts = preg_split('/[ \\x09]+/', $phrase, -1, PREG_SPLIT_NO_EMPTY); + + $phrase_parts = array(); + while (count($parts) > 0){ + $phrase_parts[] = $this->_splitCheck($parts, ' '); + for ($i = 0; $i < $this->index + 1; $i++) + array_shift($parts); + } + + for ($i = 0; $i < count($phrase_parts); $i++) { + // If quoted string: + if (substr($phrase_parts[$i], 0, 1) == '"') { + if (!$this->_validateQuotedString($phrase_parts[$i])) { + return false; + } + continue; + } + + // Otherwise it's an atom: + if (!$this->_validateAtom($phrase_parts[$i])) return false; + } + + return true; + } + + /** + * Function to validate an atom which from rfc822 is: + * atom = 1* + * + * If validation ($this->validate) has been turned off, then + * validateAtom() doesn't actually check anything. This is so that you + * can split a list of addresses up before encoding personal names + * (umlauts, etc.), for example. + * + * @access private + * @param string $atom The string to check. + * @return boolean Success or failure. + */ + function _validateAtom($atom) + { + if (!$this->validate) { + // Validation has been turned off; assume the atom is okay. + return true; + } + + // Check for any char from ASCII 0 - ASCII 127 + if (!preg_match('/^[\\x00-\\x7E]+$/i', $atom, $matches)) { + return false; + } + + // Check for specials: + if (preg_match('/[][()<>@,;\\:". ]/', $atom)) { + return false; + } + + // Check for control characters (ASCII 0-31): + if (preg_match('/[\\x00-\\x1F]+/', $atom)) { + return false; + } + + return true; + } + + /** + * Function to validate quoted string, which is: + * quoted-string = <"> *(qtext/quoted-pair) <"> + * + * @access private + * @param string $qstring The string to check + * @return boolean Success or failure. + */ + function _validateQuotedString($qstring) + { + // Leading and trailing " + $qstring = substr($qstring, 1, -1); + + // Perform check. + return !(preg_match('/(.)[\x0D\\\\"]/', $qstring, $matches) && $matches[1] != '\\'); + } + + /** + * Function to validate a mailbox, which is: + * mailbox = addr-spec ; simple address + * / phrase route-addr ; name and route-addr + * + * @access public + * @param string &$mailbox The string to check. + * @return boolean Success or failure. + */ + function validateMailbox(&$mailbox) + { + // A couple of defaults. + $phrase = ''; + $comment = ''; + $comments = array(); + + // Catch any RFC822 comments and store them separately. + $_mailbox = $mailbox; + while (strlen(trim($_mailbox)) > 0) { + $parts = explode('(', $_mailbox); + $before_comment = $this->_splitCheck($parts, '('); + if ($before_comment != $_mailbox) { + // First char should be a (. + $comment = substr(str_replace($before_comment, '', $_mailbox), 1); + $parts = explode(')', $comment); + $comment = $this->_splitCheck($parts, ')'); + $comments[] = $comment; + + // +1 is for the trailing ) + $_mailbox = substr($_mailbox, strpos($_mailbox, $comment)+strlen($comment)+1); + } else { + break; + } + } + + foreach ($comments as $comment) { + $mailbox = str_replace("($comment)", '', $mailbox); + } + + $mailbox = trim($mailbox); + + // Check for name + route-addr + if (substr($mailbox, -1) == '>' && substr($mailbox, 0, 1) != '<') { + $parts = explode('<', $mailbox); + $name = $this->_splitCheck($parts, '<'); + + $phrase = trim($name); + $route_addr = trim(substr($mailbox, strlen($name.'<'), -1)); + + if ($this->_validatePhrase($phrase) === false || ($route_addr = $this->_validateRouteAddr($route_addr)) === false) { + return false; + } + + // Only got addr-spec + } else { + // First snip angle brackets if present. + if (substr($mailbox, 0, 1) == '<' && substr($mailbox, -1) == '>') { + $addr_spec = substr($mailbox, 1, -1); + } else { + $addr_spec = $mailbox; + } + + if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { + return false; + } + } + + // Construct the object that will be returned. + $mbox = new stdClass(); + + // Add the phrase (even if empty) and comments + $mbox->personal = $phrase; + $mbox->comment = isset($comments) ? $comments : array(); + + if (isset($route_addr)) { + $mbox->mailbox = $route_addr['local_part']; + $mbox->host = $route_addr['domain']; + $route_addr['adl'] !== '' ? $mbox->adl = $route_addr['adl'] : ''; + } else { + $mbox->mailbox = $addr_spec['local_part']; + $mbox->host = $addr_spec['domain']; + } + + $mailbox = $mbox; + return true; + } + + /** + * This function validates a route-addr which is: + * route-addr = "<" [route] addr-spec ">" + * + * Angle brackets have already been removed at the point of + * getting to this function. + * + * @access private + * @param string $route_addr The string to check. + * @return mixed False on failure, or an array containing validated address/route information on success. + */ + function _validateRouteAddr($route_addr) + { + // Check for colon. + if (strpos($route_addr, ':') !== false) { + $parts = explode(':', $route_addr); + $route = $this->_splitCheck($parts, ':'); + } else { + $route = $route_addr; + } + + // If $route is same as $route_addr then the colon was in + // quotes or brackets or, of course, non existent. + if ($route === $route_addr){ + unset($route); + $addr_spec = $route_addr; + if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { + return false; + } + } else { + // Validate route part. + if (($route = $this->_validateRoute($route)) === false) { + return false; + } + + $addr_spec = substr($route_addr, strlen($route . ':')); + + // Validate addr-spec part. + if (($addr_spec = $this->_validateAddrSpec($addr_spec)) === false) { + return false; + } + } + + if (isset($route)) { + $return['adl'] = $route; + } else { + $return['adl'] = ''; + } + + $return = array_merge($return, $addr_spec); + return $return; + } + + /** + * Function to validate a route, which is: + * route = 1#("@" domain) ":" + * + * @access private + * @param string $route The string to check. + * @return mixed False on failure, or the validated $route on success. + */ + function _validateRoute($route) + { + // Split on comma. + $domains = explode(',', trim($route)); + + for ($i = 0; $i < count($domains); $i++) { + $domains[$i] = str_replace('@', '', trim($domains[$i])); + if (!$this->_validateDomain($domains[$i])) return false; + } + + return $route; + } + + /** + * Function to validate a domain, though this is not quite what + * you expect of a strict internet domain. + * + * domain = sub-domain *("." sub-domain) + * + * @access private + * @param string $domain The string to check. + * @return mixed False on failure, or the validated domain on success. + */ + function _validateDomain($domain) + { + // Note the different use of $subdomains and $sub_domains + $subdomains = explode('.', $domain); + + while (count($subdomains) > 0) { + $sub_domains[] = $this->_splitCheck($subdomains, '.'); + for ($i = 0; $i < $this->index + 1; $i++) + array_shift($subdomains); + } + + for ($i = 0; $i < count($sub_domains); $i++) { + if (!$this->_validateSubdomain(trim($sub_domains[$i]))) + return false; + } + + // Managed to get here, so return input. + return $domain; + } + + /** + * Function to validate a subdomain: + * subdomain = domain-ref / domain-literal + * + * @access private + * @param string $subdomain The string to check. + * @return boolean Success or failure. + */ + function _validateSubdomain($subdomain) + { + if (preg_match('|^\[(.*)]$|', $subdomain, $arr)){ + if (!$this->_validateDliteral($arr[1])) return false; + } else { + if (!$this->_validateAtom($subdomain)) return false; + } + + // Got here, so return successful. + return true; + } + + /** + * Function to validate a domain literal: + * domain-literal = "[" *(dtext / quoted-pair) "]" + * + * @access private + * @param string $dliteral The string to check. + * @return boolean Success or failure. + */ + function _validateDliteral($dliteral) + { + return !preg_match('/(.)[][\x0D\\\\]/', $dliteral, $matches) && $matches[1] != '\\'; + } + + /** + * Function to validate an addr-spec. + * + * addr-spec = local-part "@" domain + * + * @access private + * @param string $addr_spec The string to check. + * @return mixed False on failure, or the validated addr-spec on success. + */ + function _validateAddrSpec($addr_spec) + { + $addr_spec = trim($addr_spec); + + // Split on @ sign if there is one. + if (strpos($addr_spec, '@') !== false) { + $parts = explode('@', $addr_spec); + $local_part = $this->_splitCheck($parts, '@'); + $domain = substr($addr_spec, strlen($local_part . '@')); + + // No @ sign so assume the default domain. + } else { + $local_part = $addr_spec; + $domain = $this->default_domain; + } + + if (($local_part = $this->_validateLocalPart($local_part)) === false) return false; + if (($domain = $this->_validateDomain($domain)) === false) return false; + + // Got here so return successful. + return array('local_part' => $local_part, 'domain' => $domain); + } + + /** + * Function to validate the local part of an address: + * local-part = word *("." word) + * + * @access private + * @param string $local_part + * @return mixed False on failure, or the validated local part on success. + */ + function _validateLocalPart($local_part) + { + $parts = explode('.', $local_part); + $words = array(); + + // Split the local_part into words. + while (count($parts) > 0){ + $words[] = $this->_splitCheck($parts, '.'); + for ($i = 0; $i < $this->index + 1; $i++) { + array_shift($parts); + } + } + + // Validate each word. + for ($i = 0; $i < count($words); $i++) { + if ($this->_validatePhrase(trim($words[$i])) === false) return false; + } + + // Managed to get here, so return the input. + return $local_part; + } + + /** + * Returns an approximate count of how many addresses are + * in the given string. This is APPROXIMATE as it only splits + * based on a comma which has no preceding backslash. Could be + * useful as large amounts of addresses will end up producing + * *large* structures when used with parseAddressList(). + * + * @param string $data Addresses to count + * @return int Approximate count + */ + function approximateCount($data) + { + return count(preg_split('/(?@. This can be + * sufficient for most people. Optional stricter mode can + * be utilised which restricts mailbox characters allowed + * to alphanumeric, full stop, hyphen and underscore. + * + * @param string $data Address to check + * @param boolean $strict Optional stricter mode + * @return mixed False if it fails, an indexed array + * username/domain if it matches + */ + function isValidInetAddress($data, $strict = false) + { + $regex = $strict ? '/^([.0-9a-z_-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,4})$/i' : '/^([*+!.&#$|\'\\%\/0-9a-z^_`{}=?~:-]+)@(([0-9a-z-]+\.)+[0-9a-z]{2,4})$/i'; + if (preg_match($regex, trim($data), $matches)) { + return array($matches[1], $matches[2]); + } else { + return false; + } + } + +} diff --git a/common/PEAR/Mail/mail.php b/common/PEAR/Mail/mail.php new file mode 100644 index 0000000..c1a6a6c --- /dev/null +++ b/common/PEAR/Mail/mail.php @@ -0,0 +1,126 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: mail.php,v 1.9 2004/04/06 05:19:03 jon Exp $ + +/** + * internal PHP-mail() implementation of the PEAR Mail:: interface. + * @package Mail + * @version $Revision: 1.9 $ + */ +class Mail_mail extends Mail +{ + /** + * Any arguments to pass to the mail() function. + * @var string + */ + var $_params = ''; + + /** + * Constructor. + * + * Instantiates a new Mail_mail:: object based on the parameters + * passed in. + * + * @param string $params Extra arguments for the mail() function. + */ + function Mail_mail($params = '') + { + /* The other mail implementations accept parameters as arrays. + * In the interest of being consistent, explode an array into + * a string of parameter arguments. */ + if (is_array($params)) { + $this->_params = join(' ', $params); + } else { + $this->_params = $params; + } + + /* Because the mail() function may pass headers as command + * line arguments, we can't guarantee the use of the standard + * "\r\n" separator. Instead, we use the system's native line + * separator. */ + $this->sep = (strstr(PHP_OS, 'WIN')) ? "\r\n" : "\n"; + } + + /** + * Implements Mail_mail::send() function using php's built-in mail() + * command. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * + * @access public + */ + function send($recipients, $headers, $body) + { + // If we're passed an array of recipients, implode it. + if (is_array($recipients)) { + $recipients = implode(', ', $recipients); + } + + // Get the Subject out of the headers array so that we can + // pass it as a seperate argument to mail(). + $subject = ''; + if (isset($headers['Subject'])) { + $subject = $headers['Subject']; + unset($headers['Subject']); + } + + // Flatten the headers out. + list(,$text_headers) = Mail::prepareHeaders($headers); + + /* + * We only use mail()'s optional fifth parameter if the additional + * parameters have been provided and we're not running in safe mode. + */ + if (empty($this->_params) || ini_get('safe_mode')) { + $result = mail($recipients, $subject, $body, $text_headers); + } else { + $result = mail($recipients, $subject, $body, $text_headers, + $this->_params); + } + + /* + * If the mail() function returned failure, we need to create a + * PEAR_Error object and return it instead of the boolean result. + */ + if ($result === false) { + $result = PEAR::raiseError('mail() returned failure', + PEAR_MAIL_FAILED); + } + + return $result; + } +} diff --git a/common/PEAR/Mail/null.php b/common/PEAR/Mail/null.php new file mode 100644 index 0000000..e1f3105 --- /dev/null +++ b/common/PEAR/Mail/null.php @@ -0,0 +1,60 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: null.php,v 1.2 2004/04/06 05:19:03 jon Exp $ +// + +/** + * Null implementation of the PEAR Mail:: interface. + * @access public + * @package Mail + * @version $Revision: 1.2 $ + */ +class Mail_null extends Mail { + + /** + * Implements Mail_null::send() function. Silently discards all + * mail. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * @access public + */ + function send($recipients, $headers, $body) + { + return true; + } + +} diff --git a/common/PEAR/Mail/sendmail.php b/common/PEAR/Mail/sendmail.php new file mode 100644 index 0000000..433bcf5 --- /dev/null +++ b/common/PEAR/Mail/sendmail.php @@ -0,0 +1,131 @@ + | +// +----------------------------------------------------------------------+ + +/** + * Sendmail implementation of the PEAR Mail:: interface. + * @access public + * @package Mail + * @version $Revision: 1.5 $ + */ +class Mail_sendmail extends Mail { + + /** + * The location of the sendmail or sendmail wrapper binary on the + * filesystem. + * @var string + */ + var $sendmail_path = '/usr/sbin/sendmail'; + + /** + * Any extra command-line parameters to pass to the sendmail or + * sendmail wrapper binary. + * @var string + */ + var $sendmail_args = ''; + + /** + * Constructor. + * + * Instantiates a new Mail_sendmail:: object based on the parameters + * passed in. It looks for the following parameters: + * sendmail_path The location of the sendmail binary on the + * filesystem. Defaults to '/usr/sbin/sendmail'. + * + * sendmail_args Any extra parameters to pass to the sendmail + * or sendmail wrapper binary. + * + * If a parameter is present in the $params array, it replaces the + * default. + * + * @param array $params Hash containing any parameters different from the + * defaults. + * @access public + */ + function Mail_sendmail($params) + { + if (isset($params['sendmail_path'])) $this->sendmail_path = $params['sendmail_path']; + if (isset($params['sendmail_args'])) $this->sendmail_args = $params['sendmail_args']; + + /* + * Because we need to pass message headers to the sendmail program on + * the commandline, we can't guarantee the use of the standard "\r\n" + * separator. Instead, we use the system's native line separator. + */ + $this->sep = (strstr(PHP_OS, 'WIN')) ? "\r\n" : "\n"; + } + + /** + * Implements Mail::send() function using the sendmail + * command-line binary. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (ie, 'Subject'), and the array value + * is the header value (ie, 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * @access public + */ + function send($recipients, $headers, $body) + { + $recipients = escapeShellCmd(implode(' ', $this->parseRecipients($recipients))); + + list($from, $text_headers) = $this->prepareHeaders($headers); + if (!isset($from)) { + return new PEAR_Error('No from address given.'); + } elseif (strstr($from, ' ') || + strstr($from, ';') || + strstr($from, '&') || + strstr($from, '`')) { + return new PEAR_Error('From address specified with dangerous characters.'); + } + + $result = 0; + if (@is_executable($this->sendmail_path)) { + $from = escapeShellCmd($from); + $mail = popen($this->sendmail_path . (!empty($this->sendmail_args) ? ' ' . $this->sendmail_args : '') . " -f$from -- $recipients", 'w'); + fputs($mail, $text_headers); + fputs($mail, $this->sep); // newline to end the headers section + fputs($mail, $body); + $result = pclose($mail) >> 8 & 0xFF; // need to shift the pclose result to get the exit code + } else { + return new PEAR_Error('sendmail [' . $this->sendmail_path . '] not executable'); + } + + if ($result != 0) { + return new PEAR_Error('sendmail returned error code ' . $result); + } + + return true; + } + +} +?> diff --git a/common/PEAR/Mail/smtp.php b/common/PEAR/Mail/smtp.php new file mode 100644 index 0000000..c443ddd --- /dev/null +++ b/common/PEAR/Mail/smtp.php @@ -0,0 +1,185 @@ + | +// | Jon Parise | +// +----------------------------------------------------------------------+ + +/** + * SMTP implementation of the PEAR Mail:: interface. Requires the PEAR + * Net_SMTP:: class. + * @access public + * @package Mail + * @version $Revision: 1.13 $ + */ +class Mail_smtp extends Mail { + + /** + * The SMTP host to connect to. + * @var string + */ + var $host = 'localhost'; + + /** + * The port the SMTP server is on. + * @var integer + */ + var $port = 25; + + /** + * Should SMTP authentication be used? + * + * This value may be set to true, false or the name of a specific + * authentication method. + * + * If the value is set to true, the Net_SMTP package will attempt to use + * the best authentication method advertised by the remote SMTP server. + * + * @var mixed + */ + var $auth = false; + + /** + * The username to use if the SMTP server requires authentication. + * @var string + */ + var $username = ''; + + /** + * The password to use if the SMTP server requires authentication. + * @var string + */ + var $password = ''; + + /** + * Hostname or domain that will be sent to the remote SMTP server in the + * HELO / EHLO message. + * + * @var string + */ + var $localhost = 'localhost'; + + /** + * Constructor. + * + * Instantiates a new Mail_smtp:: object based on the parameters + * passed in. It looks for the following parameters: + * host The server to connect to. Defaults to localhost. + * port The port to connect to. Defaults to 25. + * auth SMTP authentication. Defaults to none. + * username The username to use for SMTP auth. No default. + * password The password to use for SMTP auth. No default. + * localhost The local hostname / domain. Defaults to localhost. + * + * If a parameter is present in the $params array, it replaces the + * default. + * + * @param array Hash containing any parameters different from the + * defaults. + * @access public + */ + function Mail_smtp($params) + { + if (isset($params['host'])) $this->host = $params['host']; + if (isset($params['port'])) $this->port = $params['port']; + if (isset($params['auth'])) $this->auth = $params['auth']; + if (isset($params['username'])) $this->username = $params['username']; + if (isset($params['password'])) $this->password = $params['password']; + if (isset($params['localhost'])) $this->localhost = $params['localhost']; + } + + /** + * Implements Mail::send() function using SMTP. + * + * @param mixed $recipients Either a comma-seperated list of recipients + * (RFC822 compliant), or an array of recipients, + * each RFC822 valid. This may contain recipients not + * specified in the headers, for Bcc:, resending + * messages, etc. + * + * @param array $headers The array of headers to send with the mail, in an + * associative array, where the array key is the + * header name (e.g., 'Subject'), and the array value + * is the header value (e.g., 'test'). The header + * produced from those values would be 'Subject: + * test'. + * + * @param string $body The full text of the message body, including any + * Mime parts, etc. + * + * @return mixed Returns true on success, or a PEAR_Error + * containing a descriptive error message on + * failure. + * @access public + */ + function send($recipients, $headers, $body) + { + include_once 'Net/SMTP.php'; + + if (!($smtp = new Net_SMTP($this->host, $this->port, $this->localhost))) { + return new PEAR_Error('unable to instantiate Net_SMTP object'); + } + + if (PEAR::isError($smtp->connect())) { + return new PEAR_Error('unable to connect to smtp server ' . + $this->host . ':' . $this->port); + } + + if ($this->auth) { + $method = is_string($this->auth) ? $this->auth : ''; + + if (PEAR::isError($smtp->auth($this->username, $this->password, + $method))) { + return new PEAR_Error('unable to authenticate to smtp server'); + } + } + + list($from, $text_headers) = $this->prepareHeaders($headers); + + /* + * Since few MTAs are going to allow this header to be forged unless + * it's in the MAIL FROM: exchange, we'll use Return-Path instead of + * From: if it's set. + */ + if (!empty($headers['Return-Path'])) { + $from = $headers['Return-Path']; + } + + if (!isset($from)) { + return new PEAR_Error('No from address given'); + } + + if (PEAR::isError($smtp->mailFrom($from))) { + return new PEAR_Error('unable to set sender to [' . $from . ']'); + } + + $recipients = $this->parseRecipients($recipients); + foreach($recipients as $recipient) { + if (PEAR::isError($res = $smtp->rcptTo($recipient))) { + return new PEAR_Error('unable to add recipient [' . + $recipient . ']: ' . $res->getMessage()); + } + } + + if (PEAR::isError($smtp->data($text_headers . "\r\n" . $body))) { + return new PEAR_Error('unable to send data'); + } + + $smtp->disconnect(); + return true; + } +} + +?> diff --git a/common/PEAR/Net/SMTP.php b/common/PEAR/Net/SMTP.php new file mode 100644 index 0000000..aa215cf --- /dev/null +++ b/common/PEAR/Net/SMTP.php @@ -0,0 +1,970 @@ + | +// | Jon Parise | +// | Damian Alejandro Fernandez Sosa | +// +----------------------------------------------------------------------+ + +require_once 'PEAR.php'; +require_once 'Net/Socket.php'; + +/** + * Provides an implementation of the SMTP protocol using PEAR's + * Net_Socket:: class. + * + * @package Net_SMTP + * @author Chuck Hagenbuch + * @author Jon Parise + * @author Damian Alejandro Fernandez Sosa + * + * @example basic.php A basic implementation of the Net_SMTP package. + */ +class Net_SMTP +{ + /** + * The server to connect to. + * @var string + * @access public + */ + var $host = 'localhost'; + + /** + * The port to connect to. + * @var int + * @access public + */ + var $port = 25; + + /** + * The value to give when sending EHLO or HELO. + * @var string + * @access public + */ + var $localhost = 'localhost'; + + /** + * List of supported authentication methods, in preferential order. + * @var array + * @access public + */ + var $auth_methods = array('DIGEST-MD5', 'CRAM-MD5', 'LOGIN', 'PLAIN'); + + /** + * Should debugging output be enabled? + * @var boolean + * @access private + */ + var $_debug = false; + + /** + * The socket resource being used to connect to the SMTP server. + * @var resource + * @access private + */ + var $_socket = null; + + /** + * The most recent server response code. + * @var int + * @access private + */ + var $_code = -1; + + /** + * The most recent server response arguments. + * @var array + * @access private + */ + var $_arguments = array(); + + /** + * Stores detected features of the SMTP server. + * @var array + * @access private + */ + var $_esmtp = array(); + + /** + * Instantiates a new Net_SMTP object, overriding any defaults + * with parameters that are passed in. + * + * @param string The server to connect to. + * @param int The port to connect to. + * @param string The value to give when sending EHLO or HELO. + * + * @access public + * @since 1.0 + */ + function Net_SMTP($host = null, $port = null, $localhost = null) + { + if (isset($host)) $this->host = $host; + if (isset($port)) $this->port = $port; + if (isset($localhost)) $this->localhost = $localhost; + + $this->_socket = new Net_Socket(); + + /* + * Include the Auth_SASL package. If the package is not available, + * we disable the authentication methods that depend upon it. + */ + if ((@include_once 'Auth/SASL.php') === false) { + $pos = array_search('DIGEST-MD5', $this->auth_methods); + unset($this->auth_methods[$pos]); + $pos = array_search('CRAM-MD5', $this->auth_methods); + unset($this->auth_methods[$pos]); + } + } + + /** + * Set the value of the debugging flag. + * + * @param boolean $debug New value for the debugging flag. + * + * @access public + * @since 1.1.0 + */ + function setDebug($debug) + { + $this->_debug = $debug; + } + + /** + * Send the given string of data to the server. + * + * @param string $data The string of data to send. + * + * @return mixed True on success or a PEAR_Error object on failure. + * + * @access private + * @since 1.1.0 + */ + function _send($data) + { + if ($this->_debug) { + echo "DEBUG: Send: $data\n"; + } + + if (PEAR::isError($error = $this->_socket->write($data))) { + return new PEAR_Error('Failed to write to socket: ' . + $error->getMessage()); + } + + return true; + } + + /** + * Send a command to the server with an optional string of arguments. + * A carriage return / linefeed (CRLF) sequence will be appended to each + * command string before it is sent to the SMTP server. + * + * @param string $command The SMTP command to send to the server. + * @param string $args A string of optional arguments to append + * to the command. + * + * @return mixed The result of the _send() call. + * + * @access private + * @since 1.1.0 + */ + function _put($command, $args = '') + { + if (!empty($args)) { + return $this->_send($command . ' ' . $args . "\r\n"); + } + + return $this->_send($command . "\r\n"); + } + + /** + * Read a reply from the SMTP server. The reply consists of a response + * code and a response message. + * + * @param mixed $valid The set of valid response codes. These + * may be specified as an array of integer + * values or as a single integer value. + * + * @return mixed True if the server returned a valid response code or + * a PEAR_Error object is an error condition is reached. + * + * @access private + * @since 1.1.0 + * + * @see getResponse + */ + function _parseResponse($valid) + { + $this->_code = -1; + $this->_arguments = array(); + + while ($line = $this->_socket->readLine()) { + if ($this->_debug) { + echo "DEBUG: Recv: $line\n"; + } + + /* If we receive an empty line, the connection has been closed. */ + if (empty($line)) { + $this->disconnect(); + return new PEAR_Error("Connection was unexpectedly closed"); + } + + /* Read the code and store the rest in the arguments array. */ + $code = substr($line, 0, 3); + $this->_arguments[] = trim(substr($line, 4)); + + /* Check the syntax of the response code. */ + if (is_numeric($code)) { + $this->_code = (int)$code; + } else { + $this->_code = -1; + break; + } + + /* If this is not a multiline response, we're done. */ + if (substr($line, 3, 1) != '-') { + break; + } + } + + /* Compare the server's response code with the valid code. */ + if (is_int($valid) && ($this->_code === $valid)) { + return true; + } + + /* If we were given an array of valid response codes, check each one. */ + if (is_array($valid)) { + foreach ($valid as $valid_code) { + if ($this->_code === $valid_code) { + return true; + } + } + } + + return new PEAR_Error("Invalid response code received from server"); + } + + /** + * Return a 2-tuple containing the last response from the SMTP server. + * + * @return array A two-element array: the first element contains the + * response code as an integer and the second element + * contains the response's arguments as a string. + * + * @access public + * @since 1.1.0 + */ + function getResponse() + { + return array($this->_code, join("\n", $this->_arguments)); + } + + /** + * Attempt to connect to the SMTP server. + * + * @param int $timeout The timeout value (in seconds) for the + * socket connection. + * @param bool $persistent Should a persistent socket connection + * be used? + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function connect($timeout = null, $persistent = false) + { + $result = $this->_socket->connect($this->host, $this->port, + $persistent, $timeout); + if (PEAR::isError($result)) { + return new PEAR_Error('Failed to connect socket: ' . + $result->getMessage()); + } + + if (PEAR::isError($error = $this->_parseResponse(220))) { + return $error; + } + if (PEAR::isError($error = $this->_negotiate())) { + return $error; + } + + return true; + } + + /** + * Attempt to disconnect from the SMTP server. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function disconnect() + { + if (PEAR::isError($error = $this->_put('QUIT'))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(221))) { + return $error; + } + if (PEAR::isError($error = $this->_socket->disconnect())) { + return new PEAR_Error('Failed to disconnect socket: ' . + $error->getMessage()); + } + + return true; + } + + /** + * Attempt to send the EHLO command and obtain a list of ESMTP + * extensions available, and failing that just send HELO. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * + * @access private + * @since 1.1.0 + */ + function _negotiate() + { + if (PEAR::isError($error = $this->_put('EHLO', $this->localhost))) { + return $error; + } + + if (PEAR::isError($this->_parseResponse(250))) { + /* If we receive a 503 response, we're already authenticated. */ + if ($this->_code === 503) { + return true; + } + + /* If the EHLO failed, try the simpler HELO command. */ + if (PEAR::isError($error = $this->_put('HELO', $this->localhost))) { + return $error; + } + if (PEAR::isError($this->_parseResponse(250))) { + return new PEAR_Error('HELO was not accepted: ', $this->_code); + } + + return true; + } + + foreach ($this->_arguments as $argument) { + $verb = strtok($argument, ' '); + $arguments = substr($argument, strlen($verb) + 1, + strlen($argument) - strlen($verb) - 1); + $this->_esmtp[$verb] = $arguments; + } + + return true; + } + + /** + * Returns the name of the best authentication method that the server + * has advertised. + * + * @return mixed Returns a string containing the name of the best + * supported authentication method or a PEAR_Error object + * if a failure condition is encountered. + * @access private + * @since 1.1.0 + */ + function _getBestAuthMethod() + { + $available_methods = explode(' ', $this->_esmtp['AUTH']); + + foreach ($this->auth_methods as $method) { + if (in_array($method, $available_methods)) { + return $method; + } + } + + return new PEAR_Error('No supported authentication methods'); + } + + /** + * Attempt to do SMTP authentication. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * @param string The requested authentication method. If none is + * specified, the best supported method will be used. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function auth($uid, $pwd , $method = '') + { + if (empty($this->_esmtp['AUTH'])) { + return new PEAR_Error('SMTP server does no support authentication'); + } + + /* + * If no method has been specified, get the name of the best supported + * method advertised by the SMTP server. + */ + if (empty($method)) { + if (PEAR::isError($method = $this->_getBestAuthMethod())) { + /* Return the PEAR_Error object from _getBestAuthMethod(). */ + return $method; + } + } else { + $method = strtoupper($method); + if (!in_array($method, $this->auth_methods)) { + return new PEAR_Error("$method is not a supported authentication method"); + } + } + + switch ($method) { + case 'DIGEST-MD5': + $result = $this->_authDigest_MD5($uid, $pwd); + break; + case 'CRAM-MD5': + $result = $this->_authCRAM_MD5($uid, $pwd); + break; + case 'LOGIN': + $result = $this->_authLogin($uid, $pwd); + break; + case 'PLAIN': + $result = $this->_authPlain($uid, $pwd); + break; + default: + $result = new PEAR_Error("$method is not a supported authentication method"); + break; + } + + /* If an error was encountered, return the PEAR_Error object. */ + if (PEAR::isError($result)) { + return $result; + } + + /* RFC-2554 requires us to re-negotiate ESMTP after an AUTH. */ + if (PEAR::isError($error = $this->_negotiate())) { + return $error; + } + + return true; + } + + /** + * Authenticates the user using the DIGEST-MD5 method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access private + * @since 1.1.0 + */ + function _authDigest_MD5($uid, $pwd) + { + if (PEAR::isError($error = $this->_put('AUTH', 'DIGEST-MD5'))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->_code === 503) { + return true; + } + return $error; + } + + $challenge = base64_decode($this->_arguments[0]); + $digest = &Auth_SASL::factory('digestmd5'); + $auth_str = base64_encode($digest->getResponse($uid, $pwd, $challenge, + $this->host, "smtp")); + + if (PEAR::isError($error = $this->_put($auth_str))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + return $error; + } + + /* + * We don't use the protocol's third step because SMTP doesn't allow + * subsequent authentication, so we just silently ignore it. + */ + if (PEAR::isError($error = $this->_put(' '))) { + return $error; + } + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->_parseResponse(235))) { + return $error; + } + } + + /** + * Authenticates the user using the CRAM-MD5 method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access private + * @since 1.1.0 + */ + function _authCRAM_MD5($uid, $pwd) + { + if (PEAR::isError($error = $this->_put('AUTH', 'CRAM-MD5'))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->_code === 503) { + return true; + } + return $error; + } + + $challenge = base64_decode($this->_arguments[0]); + $cram = &Auth_SASL::factory('crammd5'); + $auth_str = base64_encode($cram->getResponse($uid, $pwd, $challenge)); + + if (PEAR::isError($error = $this->_put($auth_str))) { + return $error; + } + + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->_parseResponse(235))) { + return $error; + } + } + + /** + * Authenticates the user using the LOGIN method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access private + * @since 1.1.0 + */ + function _authLogin($uid, $pwd) + { + if (PEAR::isError($error = $this->_put('AUTH', 'LOGIN'))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->_code === 503) { + return true; + } + return $error; + } + + if (PEAR::isError($error = $this->_put(base64_encode($uid)))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + return $error; + } + + if (PEAR::isError($error = $this->_put(base64_encode($pwd)))) { + return $error; + } + + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->_parseResponse(235))) { + return $error; + } + + return true; + } + + /** + * Authenticates the user using the PLAIN method. + * + * @param string The userid to authenticate as. + * @param string The password to authenticate with. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access private + * @since 1.1.0 + */ + function _authPlain($uid, $pwd) + { + if (PEAR::isError($error = $this->_put('AUTH', 'PLAIN'))) { + return $error; + } + /* 334: Continue authentication request */ + if (PEAR::isError($error = $this->_parseResponse(334))) { + /* 503: Error: already authenticated */ + if ($this->_code === 503) { + return true; + } + return $error; + } + + $auth_str = base64_encode(chr(0) . $uid . chr(0) . $pwd); + + if (PEAR::isError($error = $this->_put($auth_str))) { + return $error; + } + + /* 235: Authentication successful */ + if (PEAR::isError($error = $this->_parseResponse(235))) { + return $error; + } + + return true; + } + + /** + * Send the HELO command. + * + * @param string The domain name to say we are. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function helo($domain) + { + if (PEAR::isError($error = $this->_put('HELO', $domain))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Send the MAIL FROM: command. + * + * @param string The sender (reverse path) to set. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function mailFrom($sender) + { + if (PEAR::isError($error = $this->_put('MAIL', "FROM:<$sender>"))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Send the RCPT TO: command. + * + * @param string The recipient (forward path) to add. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function rcptTo($recipient) + { + if (PEAR::isError($error = $this->_put('RCPT', "TO:<$recipient>"))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(array(250, 251)))) { + return $error; + } + + return true; + } + + /** + * Quote the data so that it meets SMTP standards. + * + * This is provided as a separate public function to facilitate easier + * overloading for the cases where it is desirable to customize the + * quoting behavior. + * + * @param string The message text to quote. The string must be passed + * by reference, and the text will be modified in place. + * + * @access public + * @since 1.2 + */ + function quotedata(&$data) + { + /* + * Change Unix (\n) and Mac (\r) linefeeds into Internet-standard CRLF + * (\r\n) linefeeds. + */ + $data = preg_replace("/([^\r]{1})\n/", "\\1\r\n", $data); + $data = preg_replace("/\n\n/", "\n\r\n", $data); + + /* + * Because a single leading period (.) signifies an end to the data, + * legitimate leading periods need to be "doubled" (e.g. '..'). + */ + $data = preg_replace("/\n\./", "\n..", $data); + } + + /** + * Send the DATA command. + * + * @param string The message body to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function data($data) + { + /* + * RFC 1870, section 3, subsection 3 states "a value of zero indicates + * that no fixed maximum message size is in force". Furthermore, it + * says that if "the parameter is omitted no information is conveyed + * about the server's fixed maximum message size". + */ + if (isset($this->_esmtp['SIZE']) && ($this->_esmtp['SIZE'] > 0)) { + if (strlen($data) >= $this->_esmtp['SIZE']) { + $this->disconnect(); + return new PEAR_Error('Message size excedes the server limit'); + } + } + + /* Quote the data based on the SMTP standards. */ + $this->quotedata($data); + + if (PEAR::isError($error = $this->_put('DATA'))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(354))) { + return $error; + } + + if (PEAR::isError($this->_send($data . "\r\n.\r\n"))) { + return new PEAR_Error('write to socket failed'); + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Send the SEND FROM: command. + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.2.6 + */ + function sendFrom($path) + { + if (PEAR::isError($error = $this->_put('SEND', "FROM:<$path>"))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Backwards-compatibility wrapper for sendFrom(). + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * + * @access public + * @since 1.0 + * @deprecated 1.2.6 + */ + function send_from($path) + { + return sendFrom($path); + } + + /** + * Send the SOML FROM: command. + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.2.6 + */ + function somlFrom($path) + { + if (PEAR::isError($error = $this->_put('SOML', "FROM:<$path>"))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Backwards-compatibility wrapper for somlFrom(). + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * + * @access public + * @since 1.0 + * @deprecated 1.2.6 + */ + function soml_from($path) + { + return somlFrom($path); + } + + /** + * Send the SAML FROM: command. + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.2.6 + */ + function samlFrom($path) + { + if (PEAR::isError($error = $this->_put('SAML', "FROM:<$path>"))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Backwards-compatibility wrapper for samlFrom(). + * + * @param string The reverse path to send. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * + * @access public + * @since 1.0 + * @deprecated 1.2.6 + */ + function saml_from($path) + { + return samlFrom($path); + } + + /** + * Send the RSET command. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function rset() + { + if (PEAR::isError($error = $this->_put('RSET'))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Send the VRFY command. + * + * @param string The string to verify + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function vrfy($string) + { + /* Note: 251 is also a valid response code */ + if (PEAR::isError($error = $this->_put('VRFY', $string))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Send the NOOP command. + * + * @return mixed Returns a PEAR_Error with an error message on any + * kind of failure, or true on success. + * @access public + * @since 1.0 + */ + function noop() + { + if (PEAR::isError($error = $this->_put('NOOP'))) { + return $error; + } + if (PEAR::isError($error = $this->_parseResponse(250))) { + return $error; + } + + return true; + } + + /** + * Backwards-compatibility method. identifySender()'s functionality is + * now handled internally. + * + * @return boolean This method always return true. + * + * @access public + * @since 1.0 + */ + function identifySender() + { + return true; + } +} + +?> diff --git a/common/PEAR/Net/Socket.php b/common/PEAR/Net/Socket.php new file mode 100644 index 0000000..9a1cdab --- /dev/null +++ b/common/PEAR/Net/Socket.php @@ -0,0 +1,429 @@ + | +// | Chuck Hagenbuch | +// +----------------------------------------------------------------------+ +// +// $Id: Socket.php,v 1.2 2002/04/03 21:49:16 ssb Exp $ +// + +require_once 'PEAR.php'; + +/** + * Generalized Socket class. More docs to be written. + * + * @version 1.0 + * @author Stig Bakken + * @author Chuck Hagenbuch + */ +class Net_Socket extends PEAR { + + // {{{ properties + + /** Socket file pointer. */ + var $fp = null; + + /** Whether the socket is blocking. */ + var $blocking = true; + + /** Whether the socket is persistent. */ + var $persistent = false; + + /** The IP address to connect to. */ + var $addr = ''; + + /** The port number to connect to. */ + var $port = 0; + + /** Number of seconds to wait on socket connections before + assuming there's no more data. */ + var $timeout = false; + + /** Number of bytes to read at a time in readLine() and + readAll(). */ + var $lineLength = 2048; + // }}} + + // {{{ constructor + /** + * Constructs a new Net_Socket object. + * + * @access public + */ + function Net_Socket() { + $this->PEAR(); + } + // }}} + + // {{{ connect() + /** + * Connect to the specified port. If called when the socket is + * already connected, it disconnects and connects again. + * + * @param $addr string IP address or host name + * @param $port int TCP port number + * @param $persistent bool (optional) whether the connection is + * persistent (kept open between requests by the web server) + * @param $timeout int (optional) how long to wait for data + * @access public + * @return mixed true on success or error object + */ + function connect($addr, $port, $persistent = null, $timeout = null) { + if (is_resource($this->fp)) { + @fclose($this->fp); + $this->fp = null; + } + + if (strspn($addr, '.0123456789') == strlen($addr)) { + $this->addr = $addr; + } else { + $this->addr = gethostbyname($addr); + } + $this->port = $port % 65536; + if ($persistent !== null) { + $this->persistent = $persistent; + } + if ($timeout !== null) { + $this->timeout = $timeout; + } + $openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen'; + $errno = 0; + $errstr = ''; + if ($this->timeout) { + $fp = $openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout); + } else { + $fp = $openfunc($this->addr, $this->port, $errno, $errstr); + } + + if (!$fp) { + return $this->raiseError($errstr, $errno); + } + + $this->fp = $fp; + + return $this->setBlocking($this->blocking); + } + // }}} + + // {{{ disconnect() + /** + * Disconnects from the peer, closes the socket. + * + * @access public + * @return mixed true on success or an error object otherwise + */ + function disconnect() { + if (is_resource($this->fp)) { + fclose($this->fp); + $this->fp = null; + return true; + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ isBlocking() + /** + * Find out if the socket is in blocking mode. + * + * @access public + * @return bool the current blocking mode. + */ + function isBlocking() { + return $this->blocking; + } + // }}} + + // {{{ setBlocking() + /** + * Sets whether the socket connection should be blocking or + * not. A read call to a non-blocking socket will return immediately + * if there is no data available, whereas it will block until there + * is data for blocking sockets. + * + * @param $mode bool true for blocking sockets, false for nonblocking + * @access public + * @return mixed true on success or an error object otherwise + */ + function setBlocking($mode) { + if (is_resource($this->fp)) { + $this->blocking = $mode; + socket_set_blocking($this->fp, $this->blocking); + return true; + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ setTimeout() + /** + * Sets the timeout value on socket descriptor, + * expressed in the sum of seconds and microseconds + * + * @param $seconds int seconds + * @param $microseconds int microseconds + * @access public + * @return mixed true on success or an error object otherwise + */ + function setTimeout($seconds, $microseconds) { + if (is_resource($this->fp)) { + socket_set_timeout($this->fp, $seconds, $microseconds); + return true; + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ getStatus() + /** + * Returns information about an existing socket resource. + * Currently returns four entries in the result array: + * + *

+ * timed_out (bool) - The socket timed out waiting for data
+ * blocked (bool) - The socket was blocked
+ * eof (bool) - Indicates EOF event
+ * unread_bytes (int) - Number of bytes left in the socket buffer
+ *

+ * + * @access public + * @return mixed Array containing information about existing socket resource or an error object otherwise + */ + function getStatus() { + if (is_resource($this->fp)) { + return socket_get_status($this->fp); + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ gets() + /** + * Get a specified line of data + * + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function gets($size) { + if (is_resource($this->fp)) { + return fgets($this->fp, $size); + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ read() + /** + * Read a specified amount of data. This is guaranteed to return, + * and has the added benefit of getting everything in one fread() + * chunk; if you know the size of the data you're getting + * beforehand, this is definitely the way to go. + * + * @param $size The number of bytes to read from the socket. + * @access public + * @return $size bytes of data from the socket, or a PEAR_Error if + * not connected. + */ + function read($size) { + if (is_resource($this->fp)) { + return fread($this->fp, $size); + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ write() + /** + * Write a specified amount of data. + * + * @access public + * @return mixed true on success or an error object otherwise + */ + function write($data) { + if (is_resource($this->fp)) { + return fwrite($this->fp, $data); + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ writeLine() + /** + * Write a line of data to the socket, followed by a trailing "\r\n". + * + * @access public + * @return mixed fputs result, or an error + */ + function writeLine ($data) { + if (is_resource($this->fp)) { + return $this->write($data . "\r\n"); + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ eof() + /** + * Tests for end-of-file on a socket descriptor + * + * @access public + * @return bool + */ + function eof() { + return (is_resource($this->fp) && feof($this->fp)); + } + // }}} + + // {{{ readByte() + /** + * Reads a byte of data + * + * @access public + * @return 1 byte of data from the socket, or a PEAR_Error if + * not connected. + */ + function readByte() { + if (is_resource($this->fp)) { + return ord($this->read(1)); + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ readWord() + /** + * Reads a word of data + * + * @access public + * @return 1 word of data from the socket, or a PEAR_Error if + * not connected. + */ + function readWord() { + if (is_resource($this->fp)) { + $buf = $this->read(2); + return (ord($buf[0]) + (ord($buf[1]) << 8)); + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ readInt() + /** + * Reads an int of data + * + * @access public + * @return 1 int of data from the socket, or a PEAR_Error if + * not connected. + */ + function readInt() { + if (is_resource($this->fp)) { + $buf = $this->read(4); + return (ord($buf[0]) + (ord($buf[1]) << 8) + + (ord($buf[2]) << 16) + (ord($buf[3]) << 24)); + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ readString() + /** + * Reads a zeroterminated string of data + * + * @access public + * @return string, or a PEAR_Error if + * not connected. + */ + function readString() { + if (is_resource($this->fp)) { + $string = ''; + while (($char = $this->read(1)) != "\x00") { + $string .= $char; + } + return $string; + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ readIPAddress() + /** + * Reads an IP Address and returns it in a dot formated string + * + * @access public + * @return Dot formated string, or a PEAR_Error if + * not connected. + */ + function readIPAddress() { + if (is_resource($this->fp)) { + $buf = $this->read(4); + return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]), + ord($buf[2]), ord($buf[3])); + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ readLine() + /** + * Read until either the end of the socket or a newline, whichever + * comes first. Strips the trailing newline from the returned data. + * + * @access public + * @return All available data up to a newline, without that + * newline, or until the end of the socket, or a PEAR_Error if + * not connected. + */ + function readLine() { + if (is_resource($this->fp)) { + $line = ''; + $timeout = time() + $this->timeout; + while (!$this->eof() && (!$this->timeout || time() < $timeout)) { + $line .= $this->gets($this->lineLength); + if (strlen($line) >= 2 && + (substr($line, -2) == "\r\n" || + substr($line, -1) == "\n")) { + return rtrim($line); + } + } + return $line; + } + return $this->raiseError("not connected"); + } + // }}} + + // {{{ readAll() + /** + * Read until the socket closes. THIS FUNCTION WILL NOT EXIT if the + * socket is in blocking mode until the socket closes. + * + * @access public + * @return All data until the socket closes, or a PEAR_Error if + * not connected. + */ + function readAll() { + if (is_resource($this->fp)) { + $data = ''; + while (!$this->eof()) + $data .= $this->read($this->lineLength); + return $data; + } + return $this->raiseError("not connected"); + } + // }}} + +} +?> diff --git a/common/PEAR/OS/Guess.php b/common/PEAR/OS/Guess.php new file mode 100644 index 0000000..ac16131 --- /dev/null +++ b/common/PEAR/OS/Guess.php @@ -0,0 +1,265 @@ + | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Guess.php,v 1.3.6.10 2003/10/24 05:34:16 cellog Exp $ + +// {{{ uname examples + +// php_uname() without args returns the same as 'uname -a', or a PHP-custom +// string for Windows. +// PHP versions prior to 4.3 return the uname of the host where PHP was built, +// as of 4.3 it returns the uname of the host running the PHP code. +// +// PC RedHat Linux 7.1: +// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown +// +// PC Debian Potato: +// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown +// +// PC FreeBSD 3.3: +// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.3: +// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.5: +// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386 +// +// PC FreeBSD 4.5 w/uname from GNU shellutils: +// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown +// +// HP 9000/712 HP-UX 10: +// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license +// +// HP 9000/712 HP-UX 10 w/uname from GNU shellutils: +// HP-UX host B.10.10 A 9000/712 unknown +// +// IBM RS6000/550 AIX 4.3: +// AIX host 3 4 000003531C00 +// +// AIX 4.3 w/uname from GNU shellutils: +// AIX host 3 4 000003531C00 unknown +// +// SGI Onyx IRIX 6.5 w/uname from GNU shellutils: +// IRIX64 host 6.5 01091820 IP19 mips +// +// SGI Onyx IRIX 6.5: +// IRIX64 host 6.5 01091820 IP19 +// +// SparcStation 20 Solaris 8 w/uname from GNU shellutils: +// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc +// +// SparcStation 20 Solaris 8: +// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20 +// + +// }}} + +/* TODO: + * - define endianness, to allow matchSignature("bigend") etc. + */ + +class OS_Guess +{ + var $sysname; + var $nodename; + var $cpu; + var $release; + var $extra; + + function OS_Guess($uname = null) + { + list($this->sysname, + $this->release, + $this->cpu, + $this->extra, + $this->nodename) = $this->parseSignature($uname); + } + + function parseSignature($uname = null) + { + static $sysmap = array( + 'HP-UX' => 'hpux', + 'IRIX64' => 'irix', + // Darwin? + ); + static $cpumap = array( + 'i586' => 'i386', + 'i686' => 'i386', + ); + if ($uname === null) { + $uname = php_uname(); + } + $parts = split('[[:space:]]+', trim($uname)); + $n = count($parts); + + $release = $machine = $cpu = ''; + $sysname = $parts[0]; + $nodename = $parts[1]; + $cpu = $parts[$n-1]; + $extra = ''; + if ($cpu == 'unknown') { + $cpu = $parts[$n-2]; + } + + switch ($sysname) { + case 'AIX': + $release = "$parts[3].$parts[2]"; + break; + case 'Windows': + switch ($parts[1]) { + case '95/98': + $release = '9x'; + break; + default: + $release = $parts[1]; + break; + } + $cpu = 'i386'; + break; + case 'Linux': + $extra = $this->_detectGlibcVersion(); + // use only the first two digits from the kernel version + $release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]); + break; + default: + $release = ereg_replace('-.*', '', $parts[2]); + break; + } + + + if (isset($sysmap[$sysname])) { + $sysname = $sysmap[$sysname]; + } else { + $sysname = strtolower($sysname); + } + if (isset($cpumap[$cpu])) { + $cpu = $cpumap[$cpu]; + } + return array($sysname, $release, $cpu, $extra, $nodename); + } + + function _detectGlibcVersion() + { + // Use glibc's header file to + // get major and minor version number: + include_once "System.php"; + $tmpfile = System::mktemp("glibctest"); + $fp = fopen($tmpfile, "w"); + fwrite($fp, "#include \n__GLIBC__ __GLIBC_MINOR__\n"); + fclose($fp); + $cpp = popen("/usr/bin/cpp $tmpfile", "r"); + $major = $minor = 0; + while ($line = fgets($cpp, 1024)) { + if ($line{0} == '#' || trim($line) == '') { + continue; + } + if (list($major, $minor) = explode(' ', trim($line))) { + break; + } + } + pclose($cpp); + unlink($tmpfile); + if (!($major && $minor) && is_link('/lib/libc.so.6')) { + // Let's try reading the libc.so.6 symlink + if (ereg('^libc-([.*])\.so$', basename(readlink('/lib/libc.so.6')), $matches)) { + list($major, $minor) = explode('.', $matches); + } + } + if (!($major && $minor)) { + return ''; + } + return "glibc{$major}.{$minor}"; + } + + function getSignature() + { + if (empty($this->extra)) { + return "{$this->sysname}-{$this->release}-{$this->cpu}"; + } + return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}"; + } + + function getSysname() + { + return $this->sysname; + } + + function getNodename() + { + return $this->nodename; + } + + function getCpu() + { + return $this->cpu; + } + + function getRelease() + { + return $this->release; + } + + function getExtra() + { + return $this->extra; + } + + function matchSignature($match) + { + if (is_array($match)) { + $fragments = $match; + } else { + $fragments = explode('-', $match); + } + $n = count($fragments); + $matches = 0; + if ($n > 0) { + $matches += $this->_matchFragment($fragments[0], $this->sysname); + } + if ($n > 1) { + $matches += $this->_matchFragment($fragments[1], $this->release); + } + if ($n > 2) { + $matches += $this->_matchFragment($fragments[2], $this->cpu); + } + if ($n > 3) { + $matches += $this->_matchFragment($fragments[3], $this->extra); + } + return ($matches == $n); + } + + function _matchFragment($fragment, $value) + { + if (strcspn($fragment, '*?') < strlen($fragment)) { + $reg = '^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '$'; + return eregi($reg, $value); + } + return ($fragment == '*' || !strcasecmp($fragment, $value)); + } + +} + +/* + * Local Variables: + * indent-tabs-mode: nil + * c-basic-offset: 4 + * End: + */ +?> diff --git a/common/PEAR/PEAR.php b/common/PEAR/PEAR.php new file mode 100644 index 0000000..e3f4903 --- /dev/null +++ b/common/PEAR/PEAR.php @@ -0,0 +1,975 @@ + | +// | Stig Bakken | +// | Tomas V.V.Cox | +// +----------------------------------------------------------------------+ +// +// $Id: PEAR.php,v 1.50.2.18 2004/04/03 06:28:46 cellog Exp $ +// + +define('PEAR_ERROR_RETURN', 1); +define('PEAR_ERROR_PRINT', 2); +define('PEAR_ERROR_TRIGGER', 4); +define('PEAR_ERROR_DIE', 8); +define('PEAR_ERROR_CALLBACK', 16); +/** + * WARNING: obsolete + * @deprecated + */ +define('PEAR_ERROR_EXCEPTION', 32); +define('PEAR_ZE2', (function_exists('version_compare') && + version_compare(zend_version(), "2-dev", "ge"))); + +if (substr(PHP_OS, 0, 3) == 'WIN') { + define('OS_WINDOWS', true); + define('OS_UNIX', false); + define('PEAR_OS', 'Windows'); +} else { + define('OS_WINDOWS', false); + define('OS_UNIX', true); + define('PEAR_OS', 'Unix'); // blatant assumption +} + +// instant backwards compatibility +if (!defined('PATH_SEPARATOR')) { + if (OS_WINDOWS) { + define('PATH_SEPARATOR', ';'); + } else { + define('PATH_SEPARATOR', ':'); + } +} + +$GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN; +$GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE; +$GLOBALS['_PEAR_destructor_object_list'] = array(); +$GLOBALS['_PEAR_shutdown_funcs'] = array(); +$GLOBALS['_PEAR_error_handler_stack'] = array(); + +ini_set('track_errors', true); + +/** + * Base class for other PEAR classes. Provides rudimentary + * emulation of destructors. + * + * If you want a destructor in your class, inherit PEAR and make a + * destructor method called _yourclassname (same name as the + * constructor, but with a "_" prefix). Also, in your constructor you + * have to call the PEAR constructor: $this->PEAR();. + * The destructor method will be called without parameters. Note that + * at in some SAPI implementations (such as Apache), any output during + * the request shutdown (in which destructors are called) seems to be + * discarded. If you need to get any debug information from your + * destructor, use error_log(), syslog() or something similar. + * + * IMPORTANT! To use the emulated destructors you need to create the + * objects by reference: $obj =& new PEAR_child; + * + * @since PHP 4.0.2 + * @author Stig Bakken + * @see http://pear.php.net/manual/ + */ +class PEAR +{ + // {{{ properties + + /** + * Whether to enable internal debug messages. + * + * @var bool + * @access private + */ + var $_debug = false; + + /** + * Default error mode for this object. + * + * @var int + * @access private + */ + var $_default_error_mode = null; + + /** + * Default error options used for this object when error mode + * is PEAR_ERROR_TRIGGER. + * + * @var int + * @access private + */ + var $_default_error_options = null; + + /** + * Default error handler (callback) for this object, if error mode is + * PEAR_ERROR_CALLBACK. + * + * @var string + * @access private + */ + var $_default_error_handler = ''; + + /** + * Which class to use for error objects. + * + * @var string + * @access private + */ + var $_error_class = 'PEAR_Error'; + + /** + * An array of expected errors. + * + * @var array + * @access private + */ + var $_expected_errors = array(); + + // }}} + + // {{{ constructor + + /** + * Constructor. Registers this object in + * $_PEAR_destructor_object_list for destructor emulation if a + * destructor object exists. + * + * @param string $error_class (optional) which class to use for + * error objects, defaults to PEAR_Error. + * @access public + * @return void + */ + function PEAR($error_class = null) + { + $classname = get_class($this); + if ($this->_debug) { + print "PEAR constructor called, class=$classname\n"; + } + if ($error_class !== null) { + $this->_error_class = $error_class; + } + while ($classname) { + $destructor = "_$classname"; + if (method_exists($this, $destructor)) { + global $_PEAR_destructor_object_list; + $_PEAR_destructor_object_list[] = &$this; + break; + } else { + $classname = get_parent_class($classname); + } + } + } + + // }}} + // {{{ destructor + + /** + * Destructor (the emulated type of...). Does nothing right now, + * but is included for forward compatibility, so subclass + * destructors should always call it. + * + * See the note in the class desciption about output from + * destructors. + * + * @access public + * @return void + */ + function _PEAR() { + if ($this->_debug) { + printf("PEAR destructor called, class=%s\n", get_class($this)); + } + } + + // }}} + // {{{ getStaticProperty() + + /** + * If you have a class that's mostly/entirely static, and you need static + * properties, you can use this method to simulate them. Eg. in your method(s) + * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar'); + * You MUST use a reference, or they will not persist! + * + * @access public + * @param string $class The calling classname, to prevent clashes + * @param string $var The variable to retrieve. + * @return mixed A reference to the variable. If not set it will be + * auto initialised to NULL. + */ + function &getStaticProperty($class, $var) + { + static $properties; + return $properties[$class][$var]; + } + + // }}} + // {{{ registerShutdownFunc() + + /** + * Use this function to register a shutdown method for static + * classes. + * + * @access public + * @param mixed $func The function name (or array of class/method) to call + * @param mixed $args The arguments to pass to the function + * @return void + */ + function registerShutdownFunc($func, $args = array()) + { + $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args); + } + + // }}} + // {{{ isError() + + /** + * Tell whether a value is a PEAR error. + * + * @param mixed $data the value to test + * @param int $code if $data is an error object, return true + * only if $code is a string and + * $obj->getMessage() == $code or + * $code is an integer and $obj->getCode() == $code + * @access public + * @return bool true if parameter is an error + */ + function isError($data, $code = null) + { + if (is_a($data, 'PEAR_Error')) { + if (is_null($code)) { + return true; + } elseif (is_string($code)) { + return $data->getMessage() == $code; + } else { + return $data->getCode() == $code; + } + } + return false; + } + + // }}} + // {{{ setErrorHandling() + + /** + * Sets how errors generated by this object should be handled. + * Can be invoked both in objects and statically. If called + * statically, setErrorHandling sets the default behaviour for all + * PEAR objects. If called in an object, setErrorHandling sets + * the default behaviour for that object. + * + * @param int $mode + * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION. + * + * @param mixed $options + * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one + * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * + * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected + * to be the callback function or method. A callback + * function is a string with the name of the function, a + * callback method is an array of two elements: the element + * at index 0 is the object, and the element at index 1 is + * the name of the method to call in the object. + * + * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is + * a printf format string used when printing the error + * message. + * + * @access public + * @return void + * @see PEAR_ERROR_RETURN + * @see PEAR_ERROR_PRINT + * @see PEAR_ERROR_TRIGGER + * @see PEAR_ERROR_DIE + * @see PEAR_ERROR_CALLBACK + * @see PEAR_ERROR_EXCEPTION + * + * @since PHP 4.0.5 + */ + + function setErrorHandling($mode = null, $options = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + $setmode = &$this->_default_error_mode; + $setoptions = &$this->_default_error_options; + } else { + $setmode = &$GLOBALS['_PEAR_default_error_mode']; + $setoptions = &$GLOBALS['_PEAR_default_error_options']; + } + + switch ($mode) { + case PEAR_ERROR_EXCEPTION: + case PEAR_ERROR_RETURN: + case PEAR_ERROR_PRINT: + case PEAR_ERROR_TRIGGER: + case PEAR_ERROR_DIE: + case null: + $setmode = $mode; + $setoptions = $options; + break; + + case PEAR_ERROR_CALLBACK: + $setmode = $mode; + // class/object method callback + if (is_callable($options)) { + $setoptions = $options; + } else { + trigger_error("invalid error callback", E_USER_WARNING); + } + break; + + default: + trigger_error("invalid error mode", E_USER_WARNING); + break; + } + } + + // }}} + // {{{ expectError() + + /** + * This method is used to tell which errors you expect to get. + * Expected errors are always returned with error mode + * PEAR_ERROR_RETURN. Expected error codes are stored in a stack, + * and this method pushes a new element onto it. The list of + * expected errors are in effect until they are popped off the + * stack with the popExpect() method. + * + * Note that this method can not be called statically + * + * @param mixed $code a single error code or an array of error codes to expect + * + * @return int the new depth of the "expected errors" stack + * @access public + */ + function expectError($code = '*') + { + if (is_array($code)) { + array_push($this->_expected_errors, $code); + } else { + array_push($this->_expected_errors, array($code)); + } + return sizeof($this->_expected_errors); + } + + // }}} + // {{{ popExpect() + + /** + * This method pops one element off the expected error codes + * stack. + * + * @return array the list of error codes that were popped + */ + function popExpect() + { + return array_pop($this->_expected_errors); + } + + // }}} + // {{{ _checkDelExpect() + + /** + * This method checks unsets an error code if available + * + * @param mixed error code + * @return bool true if the error code was unset, false otherwise + * @access private + * @since PHP 4.3.0 + */ + function _checkDelExpect($error_code) + { + $deleted = false; + + foreach ($this->_expected_errors AS $key => $error_array) { + if (in_array($error_code, $error_array)) { + unset($this->_expected_errors[$key][array_search($error_code, $error_array)]); + $deleted = true; + } + + // clean up empty arrays + if (0 == count($this->_expected_errors[$key])) { + unset($this->_expected_errors[$key]); + } + } + return $deleted; + } + + // }}} + // {{{ delExpect() + + /** + * This method deletes all occurences of the specified element from + * the expected error codes stack. + * + * @param mixed $error_code error code that should be deleted + * @return mixed list of error codes that were deleted or error + * @access public + * @since PHP 4.3.0 + */ + function delExpect($error_code) + { + $deleted = false; + + if ((is_array($error_code) && (0 != count($error_code)))) { + // $error_code is a non-empty array here; + // we walk through it trying to unset all + // values + foreach($error_code as $key => $error) { + if ($this->_checkDelExpect($error)) { + $deleted = true; + } else { + $deleted = false; + } + } + return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } elseif (!empty($error_code)) { + // $error_code comes alone, trying to unset it + if ($this->_checkDelExpect($error_code)) { + return true; + } else { + return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME + } + } else { + // $error_code is empty + return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME + } + } + + // }}} + // {{{ raiseError() + + /** + * This method is a wrapper that returns an instance of the + * configured error class with this object's default error + * handling applied. If the $mode and $options parameters are not + * specified, the object's defaults are used. + * + * @param mixed $message a text error message or a PEAR error object + * + * @param int $code a numeric error code (it is up to your class + * to define these if you want to use codes) + * + * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT, + * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE, + * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION. + * + * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter + * specifies the PHP-internal error level (one of + * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR). + * If $mode is PEAR_ERROR_CALLBACK, this + * parameter specifies the callback function or + * method. In other error modes this parameter + * is ignored. + * + * @param string $userinfo If you need to pass along for example debug + * information, this parameter is meant for that. + * + * @param string $error_class The returned error object will be + * instantiated from this class, if specified. + * + * @param bool $skipmsg If true, raiseError will only pass error codes, + * the error message parameter will be dropped. + * + * @access public + * @return object a PEAR error object + * @see PEAR::setErrorHandling + * @since PHP 4.0.5 + */ + function raiseError($message = null, + $code = null, + $mode = null, + $options = null, + $userinfo = null, + $error_class = null, + $skipmsg = false) + { + // The error is yet a PEAR error object + if (is_object($message)) { + $code = $message->getCode(); + $userinfo = $message->getUserInfo(); + $error_class = $message->getType(); + $message->error_message_prefix = ''; + $message = $message->getMessage(); + } + + if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) { + if ($exp[0] == "*" || + (is_int(reset($exp)) && in_array($code, $exp)) || + (is_string(reset($exp)) && in_array($message, $exp))) { + $mode = PEAR_ERROR_RETURN; + } + } + // No mode given, try global ones + if ($mode === null) { + // Class error handler + if (isset($this) && isset($this->_default_error_mode)) { + $mode = $this->_default_error_mode; + $options = $this->_default_error_options; + // Global error handler + } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) { + $mode = $GLOBALS['_PEAR_default_error_mode']; + $options = $GLOBALS['_PEAR_default_error_options']; + } + } + + if ($error_class !== null) { + $ec = $error_class; + } elseif (isset($this) && isset($this->_error_class)) { + $ec = $this->_error_class; + } else { + $ec = 'PEAR_Error'; + } + if ($skipmsg) { + return new $ec($code, $mode, $options, $userinfo); + } else { + return new $ec($message, $code, $mode, $options, $userinfo); + } + } + + // }}} + // {{{ throwError() + + /** + * Simpler form of raiseError with fewer options. In most cases + * message, code and userinfo are enough. + * + * @param string $message + * + */ + function throwError($message = null, + $code = null, + $userinfo = null) + { + if (isset($this) && is_a($this, 'PEAR')) { + return $this->raiseError($message, $code, null, null, $userinfo); + } else { + return PEAR::raiseError($message, $code, null, null, $userinfo); + } + } + + // }}} + // {{{ pushErrorHandling() + + /** + * Push a new error handler on top of the error handler options stack. With this + * you can easily override the actual error handler for some code and restore + * it later with popErrorHandling. + * + * @param mixed $mode (same as setErrorHandling) + * @param mixed $options (same as setErrorHandling) + * + * @return bool Always true + * + * @see PEAR::setErrorHandling + */ + function pushErrorHandling($mode, $options = null) + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + if (isset($this) && is_a($this, 'PEAR')) { + $def_mode = &$this->_default_error_mode; + $def_options = &$this->_default_error_options; + } else { + $def_mode = &$GLOBALS['_PEAR_default_error_mode']; + $def_options = &$GLOBALS['_PEAR_default_error_options']; + } + $stack[] = array($def_mode, $def_options); + + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + $stack[] = array($mode, $options); + return true; + } + + // }}} + // {{{ popErrorHandling() + + /** + * Pop the last error handler used + * + * @return bool Always true + * + * @see PEAR::pushErrorHandling + */ + function popErrorHandling() + { + $stack = &$GLOBALS['_PEAR_error_handler_stack']; + array_pop($stack); + list($mode, $options) = $stack[sizeof($stack) - 1]; + array_pop($stack); + if (isset($this) && is_a($this, 'PEAR')) { + $this->setErrorHandling($mode, $options); + } else { + PEAR::setErrorHandling($mode, $options); + } + return true; + } + + // }}} + // {{{ loadExtension() + + /** + * OS independant PHP extension load. Remember to take care + * on the correct extension name for case sensitive OSes. + * + * @param string $ext The extension name + * @return bool Success or not on the dl() call + */ + function loadExtension($ext) + { + if (!extension_loaded($ext)) { + // if either returns true dl() will produce a FATAL error, stop that + if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) { + return false; + } + if (OS_WINDOWS) { + $suffix = '.dll'; + } elseif (PHP_OS == 'HP-UX') { + $suffix = '.sl'; + } elseif (PHP_OS == 'AIX') { + $suffix = '.a'; + } elseif (PHP_OS == 'OSX') { + $suffix = '.bundle'; + } else { + $suffix = '.so'; + } + return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix); + } + return true; + } + + // }}} +} + +// {{{ _PEAR_call_destructors() + +function _PEAR_call_destructors() +{ + global $_PEAR_destructor_object_list; + if (is_array($_PEAR_destructor_object_list) && + sizeof($_PEAR_destructor_object_list)) + { + reset($_PEAR_destructor_object_list); + while (list($k, $objref) = each($_PEAR_destructor_object_list)) { + $classname = get_class($objref); + while ($classname) { + $destructor = "_$classname"; + if (method_exists($objref, $destructor)) { + $objref->$destructor(); + break; + } else { + $classname = get_parent_class($classname); + } + } + } + // Empty the object list to ensure that destructors are + // not called more than once. + $_PEAR_destructor_object_list = array(); + } + + // Now call the shutdown functions + if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) { + foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) { + call_user_func_array($value[0], $value[1]); + } + } +} + +// }}} + +class PEAR_Error +{ + // {{{ properties + + var $error_message_prefix = ''; + var $mode = PEAR_ERROR_RETURN; + var $level = E_USER_NOTICE; + var $code = -1; + var $message = ''; + var $userinfo = ''; + var $backtrace = null; + + // }}} + // {{{ constructor + + /** + * PEAR_Error constructor + * + * @param string $message message + * + * @param int $code (optional) error code + * + * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN, + * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER, + * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION + * + * @param mixed $options (optional) error level, _OR_ in the case of + * PEAR_ERROR_CALLBACK, the callback function or object/method + * tuple. + * + * @param string $userinfo (optional) additional user/debug info + * + * @access public + * + */ + function PEAR_Error($message = 'unknown error', $code = null, + $mode = null, $options = null, $userinfo = null) + { + if ($mode === null) { + $mode = PEAR_ERROR_RETURN; + } + $this->message = $message; + $this->code = $code; + $this->mode = $mode; + $this->userinfo = $userinfo; + if (function_exists("debug_backtrace")) { + $this->backtrace = debug_backtrace(); + } + if ($mode & PEAR_ERROR_CALLBACK) { + $this->level = E_USER_NOTICE; + $this->callback = $options; + } else { + if ($options === null) { + $options = E_USER_NOTICE; + } + $this->level = $options; + $this->callback = null; + } + if ($this->mode & PEAR_ERROR_PRINT) { + if (is_null($options) || is_int($options)) { + $format = "%s"; + } else { + $format = $options; + } + printf($format, $this->getMessage()); + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + trigger_error($this->getMessage(), $this->level); + } + if ($this->mode & PEAR_ERROR_DIE) { + $msg = $this->getMessage(); + if (is_null($options) || is_int($options)) { + $format = "%s"; + if (substr($msg, -1) != "\n") { + $msg .= "\n"; + } + } else { + $format = $options; + } + die(sprintf($format, $msg)); + } + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_callable($this->callback)) { + call_user_func($this->callback, $this); + } + } + if ($this->mode & PEAR_ERROR_EXCEPTION) { + trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_ErrorStack for exceptions", E_USER_WARNING); + eval('$e = new Exception($this->message, $this->code);$e->PEAR_Error = $this;throw($e);'); + } + } + + // }}} + // {{{ getMode() + + /** + * Get the error mode from an error object. + * + * @return int error mode + * @access public + */ + function getMode() { + return $this->mode; + } + + // }}} + // {{{ getCallback() + + /** + * Get the callback function/method from an error object. + * + * @return mixed callback function or object/method array + * @access public + */ + function getCallback() { + return $this->callback; + } + + // }}} + // {{{ getMessage() + + + /** + * Get the error message from an error object. + * + * @return string full error message + * @access public + */ + function getMessage() + { + return ($this->error_message_prefix . $this->message); + } + + + // }}} + // {{{ getCode() + + /** + * Get error code from an error object + * + * @return int error code + * @access public + */ + function getCode() + { + return $this->code; + } + + // }}} + // {{{ getType() + + /** + * Get the name of this error/exception. + * + * @return string error/exception name (type) + * @access public + */ + function getType() + { + return get_class($this); + } + + // }}} + // {{{ getUserInfo() + + /** + * Get additional user-supplied information. + * + * @return string user-supplied information + * @access public + */ + function getUserInfo() + { + return $this->userinfo; + } + + // }}} + // {{{ getDebugInfo() + + /** + * Get additional debug information supplied by the application. + * + * @return string debug information + * @access public + */ + function getDebugInfo() + { + return $this->getUserInfo(); + } + + // }}} + // {{{ getBacktrace() + + /** + * Get the call backtrace from where the error was generated. + * Supported with PHP 4.3.0 or newer. + * + * @param int $frame (optional) what frame to fetch + * @return array Backtrace, or NULL if not available. + * @access public + */ + function getBacktrace($frame = null) + { + if ($frame === null) { + return $this->backtrace; + } + return $this->backtrace[$frame]; + } + + // }}} + // {{{ addUserInfo() + + function addUserInfo($info) + { + if (empty($this->userinfo)) { + $this->userinfo = $info; + } else { + $this->userinfo .= " ** $info"; + } + } + + // }}} + // {{{ toString() + + /** + * Make a string representation of this object. + * + * @return string a string with an object summary + * @access public + */ + function toString() { + $modes = array(); + $levels = array(E_USER_NOTICE => 'notice', + E_USER_WARNING => 'warning', + E_USER_ERROR => 'error'); + if ($this->mode & PEAR_ERROR_CALLBACK) { + if (is_array($this->callback)) { + $callback = get_class($this->callback[0]) . '::' . + $this->callback[1]; + } else { + $callback = $this->callback; + } + return sprintf('[%s: message="%s" code=%d mode=callback '. + 'callback=%s prefix="%s" info="%s"]', + get_class($this), $this->message, $this->code, + $callback, $this->error_message_prefix, + $this->userinfo); + } + if ($this->mode & PEAR_ERROR_PRINT) { + $modes[] = 'print'; + } + if ($this->mode & PEAR_ERROR_TRIGGER) { + $modes[] = 'trigger'; + } + if ($this->mode & PEAR_ERROR_DIE) { + $modes[] = 'die'; + } + if ($this->mode & PEAR_ERROR_RETURN) { + $modes[] = 'return'; + } + return sprintf('[%s: message="%s" code=%d mode=%s level=%s '. + 'prefix="%s" info="%s"]', + get_class($this), $this->message, $this->code, + implode("|", $modes), $levels[$this->level], + $this->error_message_prefix, + $this->userinfo); + } + + // }}} +} + +register_shutdown_function("_PEAR_call_destructors"); + +/* + * Local Variables: + * mode: php + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ +?> diff --git a/common/PEAR/PEAR/Autoloader.php b/common/PEAR/PEAR/Autoloader.php new file mode 100644 index 0000000..354ab2f --- /dev/null +++ b/common/PEAR/PEAR/Autoloader.php @@ -0,0 +1,208 @@ + | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Autoloader.php,v 1.4.6.12 2004/02/27 02:22:05 cellog Exp $ + +if (!extension_loaded("overload")) { + // die hard without ext/overload + die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader"); +} + +require_once "PEAR.php"; + +/** + * This class is for objects where you want to separate the code for + * some methods into separate classes. This is useful if you have a + * class with not-frequently-used methods that contain lots of code + * that you would like to avoid always parsing. + * + * The PEAR_Autoloader class provides autoloading and aggregation. + * The autoloading lets you set up in which classes the separated + * methods are found. Aggregation is the technique used to import new + * methods, an instance of each class providing separated methods is + * stored and called every time the aggregated method is called. + * + * @author Stig Sther Bakken + */ +class PEAR_Autoloader extends PEAR +{ + // {{{ properties + + /** + * Map of methods and classes where they are defined + * + * @var array + * + * @access private + */ + var $_autoload_map = array(); + + /** + * Map of methods and aggregate objects + * + * @var array + * + * @access private + */ + var $_method_map = array(); + + // }}} + // {{{ addAutoload() + + /** + * Add one or more autoload entries. + * + * @param string $method which method to autoload + * + * @param string $classname (optional) which class to find the method in. + * If the $method parameter is an array, this + * parameter may be omitted (and will be ignored + * if not), and the $method parameter will be + * treated as an associative array with method + * names as keys and class names as values. + * + * @return void + * + * @access public + */ + function addAutoload($method, $classname = null) + { + if (is_array($method)) { + array_walk($method, create_function('$a,&$b', '$b = strtolower($b);')); + $this->_autoload_map = array_merge($this->_autoload_map, $method); + } else { + $this->_autoload_map[strtolower($method)] = $classname; + } + } + + // }}} + // {{{ removeAutoload() + + /** + * Remove an autoload entry. + * + * @param string $method which method to remove the autoload entry for + * + * @return bool TRUE if an entry was removed, FALSE if not + * + * @access public + */ + function removeAutoload($method) + { + $method = strtolower($method); + $ok = isset($this->_autoload_map[$method]); + unset($this->_autoload_map[$method]); + return $ok; + } + + // }}} + // {{{ addAggregateObject() + + /** + * Add an aggregate object to this object. If the specified class + * is not defined, loading it will be attempted following PEAR's + * file naming scheme. All the methods in the class will be + * aggregated, except private ones (name starting with an + * underscore) and constructors. + * + * @param string $classname what class to instantiate for the object. + * + * @return void + * + * @access public + */ + function addAggregateObject($classname) + { + $classname = strtolower($classname); + if (!class_exists($classname)) { + $include_file = preg_replace('/[^a-z0-9]/i', '_', $classname); + include_once $include_file; + } + $obj =& new $classname; + $methods = get_class_methods($classname); + foreach ($methods as $method) { + // don't import priviate methods and constructors + if ($method{0} != '_' && $method != $classname) { + $this->_method_map[$method] = $obj; + } + } + } + + // }}} + // {{{ removeAggregateObject() + + /** + * Remove an aggregate object. + * + * @param string $classname the class of the object to remove + * + * @return bool TRUE if an object was removed, FALSE if not + * + * @access public + */ + function removeAggregateObject($classname) + { + $ok = false; + $classname = strtolower($classname); + reset($this->_method_map); + while (list($method, $obj) = each($this->_method_map)) { + if (is_a($obj, $classname)) { + unset($this->_method_map[$method]); + $ok = true; + } + } + return $ok; + } + + // }}} + // {{{ __call() + + /** + * Overloaded object call handler, called each time an + * undefined/aggregated method is invoked. This method repeats + * the call in the right aggregate object and passes on the return + * value. + * + * @param string $method which method that was called + * + * @param string $args An array of the parameters passed in the + * original call + * + * @return mixed The return value from the aggregated method, or a PEAR + * error if the called method was unknown. + */ + function __call($method, $args, &$retval) + { + $method = strtolower($method); + if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) { + $this->addAggregateObject($this->_autoload_map[$method]); + } + if (isset($this->_method_map[$method])) { + $retval = call_user_func_array(array($this->_method_map[$method], $method), $args); + return true; + } + return false; + } + + // }}} +} + +overload("PEAR_Autoloader"); + +?> diff --git a/common/PEAR/PEAR/Builder.php b/common/PEAR/PEAR/Builder.php new file mode 100644 index 0000000..cfa6e4a --- /dev/null +++ b/common/PEAR/PEAR/Builder.php @@ -0,0 +1,392 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Builder.php,v 1.7.4.12 2004/06/08 18:15:22 cellog Exp $ + +require_once 'PEAR/Common.php'; + +/** + * Class to handle building (compiling) extensions. + * + * @author Stig Sther Bakken + */ +class PEAR_Builder extends PEAR_Common +{ + // {{{ properties + + var $php_api_version = 0; + var $zend_module_api_no = 0; + var $zend_extension_api_no = 0; + + var $extensions_built = array(); + + var $current_callback = null; + + // used for msdev builds + var $_lastline = null; + var $_firstline = null; + // }}} + // {{{ constructor + + /** + * PEAR_Builder constructor. + * + * @param object $ui user interface object (instance of PEAR_Frontend_*) + * + * @access public + */ + function PEAR_Builder(&$ui) + { + parent::PEAR_Common(); + $this->setFrontendObject($ui); + } + + // }}} + + // {{{ _build_win32() + + /** + * Build an extension from source on windows. + * requires msdev + */ + function _build_win32($descfile, $callback = null) + { + if (PEAR::isError($info = $this->infoFromDescriptionFile($descfile))) { + return $info; + } + $dir = dirname($descfile); + $old_cwd = getcwd(); + + if (!@chdir($dir)) { + return $this->raiseError("could not chdir to $dir"); + } + $this->log(2, "building in $dir"); + + $dsp = $info['package'].'.dsp'; + if (!@is_file("$dir/$dsp")) { + return $this->raiseError("The DSP $dsp does not exist."); + } + // XXX TODO: make release build type configurable + $command = 'msdev '.$dsp.' /MAKE "'.$info['package']. ' - Release"'; + + $this->current_callback = $callback; + $err = $this->_runCommand($command, array(&$this, 'msdevCallback')); + if (PEAR::isError($err)) { + return $err; + } + + // figure out the build platform and type + $platform = 'Win32'; + $buildtype = 'Release'; + if (preg_match('/.*?'.$info['package'].'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) { + $platform = $matches[1]; + $buildtype = $matches[2]; + } + + if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/',$this->_lastline,$matches)) { + if ($matches[2]) { + // there were errors in the build + return $this->raiseError("There were errors during compilation."); + } + $out = $matches[1]; + } else { + return $this->raiseError("Did not understand the completion status returned from msdev.exe."); + } + + // msdev doesn't tell us the output directory :/ + // open the dsp, find /out and use that directory + $dsptext = join(file($dsp),''); + + // this regex depends on the build platform and type having been + // correctly identified above. + $regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'. + $info['package'].'\s-\s'. + $platform.'\s'. + $buildtype.'").*?'. + '\/out:"(.*?)"/is'; + + if ($dsptext && preg_match($regex,$dsptext,$matches)) { + // what we get back is a relative path to the output file itself. + $outfile = realpath($matches[2]); + } else { + return $this->raiseError("Could not retrieve output information from $dsp."); + } + if (@copy($outfile, "$dir/$out")) { + $outfile = "$dir/$out"; + } + + $built_files[] = array( + 'file' => "$outfile", + 'php_api' => $this->php_api_version, + 'zend_mod_api' => $this->zend_module_api_no, + 'zend_ext_api' => $this->zend_extension_api_no, + ); + + return $built_files; + } + // }}} + + // {{{ msdevCallback() + function msdevCallback($what, $data) + { + if (!$this->_firstline) + $this->_firstline = $data; + $this->_lastline = $data; + } + // }}} + + // {{{ build() + + /** + * Build an extension from source. Runs "phpize" in the source + * directory, but compiles in a temporary directory + * (/var/tmp/pear-build-USER/PACKAGE-VERSION). + * + * @param string $descfile path to XML package description file + * + * @param mixed $callback callback function used to report output, + * see PEAR_Builder::_runCommand for details + * + * @return array an array of associative arrays with built files, + * format: + * array( array( 'file' => '/path/to/ext.so', + * 'php_api' => YYYYMMDD, + * 'zend_mod_api' => YYYYMMDD, + * 'zend_ext_api' => YYYYMMDD ), + * ... ) + * + * @access public + * + * @see PEAR_Builder::_runCommand + * @see PEAR_Common::infoFromDescriptionFile + */ + function build($descfile, $callback = null) + { + if (PEAR_OS == "Windows") { + return $this->_build_win32($descfile,$callback); + } + if (PEAR_OS != 'Unix') { + return $this->raiseError("building extensions not supported on this platform"); + } + if (PEAR::isError($info = $this->infoFromDescriptionFile($descfile))) { + return $info; + } + $dir = dirname($descfile); + $old_cwd = getcwd(); + if (!@chdir($dir)) { + return $this->raiseError("could not chdir to $dir"); + } + $vdir = "$info[package]-$info[version]"; + if (is_dir($vdir)) { + chdir($vdir); + } + $dir = getcwd(); + $this->log(2, "building in $dir"); + $this->current_callback = $callback; + putenv('PATH=' . getenv('PATH') . ':' . $this->config->get('bin_dir')); + $err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback')); + if (PEAR::isError($err)) { + return $err; + } + if (!$err) { + return $this->raiseError("`phpize' failed"); + } + + // {{{ start of interactive part + $configure_command = "$dir/configure"; + if (isset($info['configure_options'])) { + foreach ($info['configure_options'] as $o) { + list($r) = $this->ui->userDialog('build', + array($o['prompt']), + array('text'), + array(@$o['default'])); + if (substr($o['name'], 0, 5) == 'with-' && + ($r == 'yes' || $r == 'autodetect')) { + $configure_command .= " --$o[name]"; + } else { + $configure_command .= " --$o[name]=".trim($r); + } + } + } + // }}} end of interactive part + + // FIXME make configurable + if(!$user=getenv('USER')){ + $user='defaultuser'; + } + $build_basedir = "/var/tmp/pear-build-$user"; + $build_dir = "$build_basedir/$info[package]-$info[version]"; + $this->log(1, "building in $build_dir"); + if (is_dir($build_dir)) { + System::rm("-rf $build_dir"); + } + if (!System::mkDir("-p $build_dir")) { + return $this->raiseError("could not create build dir: $build_dir"); + } + $this->addTempFile($build_dir); + if (getenv('MAKE')) { + $make_command = getenv('MAKE'); + } else { + $make_command = 'make'; + } + $to_run = array( + $configure_command, + $make_command, + ); + if (!@chdir($build_dir)) { + return $this->raiseError("could not chdir to $build_dir"); + } + foreach ($to_run as $cmd) { + $err = $this->_runCommand($cmd, $callback); + if (PEAR::isError($err)) { + chdir($old_cwd); + return $err; + } + if (!$err) { + chdir($old_cwd); + return $this->raiseError("`$cmd' failed"); + } + } + if (!($dp = opendir("modules"))) { + chdir($old_cwd); + return $this->raiseError("no `modules' directory found"); + } + $built_files = array(); + while ($ent = readdir($dp)) { + if ($ent{0} == '.' || substr($ent, -3) == '.la') { + continue; + } + // harvest! + if (@copy("modules/$ent", "$dir/$ent")) { + $built_files[] = array( + 'file' => "$dir/$ent", + 'php_api' => $this->php_api_version, + 'zend_mod_api' => $this->zend_module_api_no, + 'zend_ext_api' => $this->zend_extension_api_no, + ); + + $this->log(1, "$ent copied to $dir/$ent"); + } else { + chdir($old_cwd); + return $this->raiseError("failed copying $ent to $dir"); + } + } + closedir($dp); + chdir($old_cwd); + return $built_files; + } + + // }}} + // {{{ phpizeCallback() + + /** + * Message callback function used when running the "phpize" + * program. Extracts the API numbers used. Ignores other message + * types than "cmdoutput". + * + * @param string $what the type of message + * @param mixed $data the message + * + * @return void + * + * @access public + */ + function phpizeCallback($what, $data) + { + if ($what != 'cmdoutput') { + return; + } + $this->log(1, rtrim($data)); + if (preg_match('/You should update your .aclocal.m4/', $data)) { + return; + } + $matches = array(); + if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) { + $member = preg_replace('/[^a-z]/', '_', strtolower($matches[1])); + $apino = (int)$matches[2]; + if (isset($this->$member)) { + $this->$member = $apino; + //$msg = sprintf("%-22s : %d", $matches[1], $apino); + //$this->log(1, $msg); + } + } + } + + // }}} + // {{{ _runCommand() + + /** + * Run an external command, using a message callback to report + * output. The command will be run through popen and output is + * reported for every line with a "cmdoutput" message with the + * line string, including newlines, as payload. + * + * @param string $command the command to run + * + * @param mixed $callback (optional) function to use as message + * callback + * + * @return bool whether the command was successful (exit code 0 + * means success, any other means failure) + * + * @access private + */ + function _runCommand($command, $callback = null) + { + $this->log(1, "running: $command"); + $pp = @popen("$command 2>&1", "r"); + if (!$pp) { + return $this->raiseError("failed to run `$command'"); + } + if ($callback && $callback[0]->debug == 1) { + $olddbg = $callback[0]->debug; + $callback[0]->debug = 2; + } + + while ($line = fgets($pp, 1024)) { + if ($callback) { + call_user_func($callback, 'cmdoutput', $line); + } else { + $this->log(2, rtrim($line)); + } + } + if ($callback && isset($olddbg)) { + $callback[0]->debug = $olddbg; + } + $exitcode = @pclose($pp); + return ($exitcode == 0); + } + + // }}} + // {{{ log() + + function log($level, $msg) + { + if ($this->current_callback) { + if ($this->debug >= $level) { + call_user_func($this->current_callback, 'output', $msg); + } + return; + } + return PEAR_Common::log($level, $msg); + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Command.php b/common/PEAR/PEAR/Command.php new file mode 100644 index 0000000..25433d8 --- /dev/null +++ b/common/PEAR/PEAR/Command.php @@ -0,0 +1,397 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Command.php,v 1.16.4.12 2004/02/27 02:24:16 cellog Exp $ + + +require_once "PEAR.php"; + +/** + * List of commands and what classes they are implemented in. + * @var array command => implementing class + */ +$GLOBALS['_PEAR_Command_commandlist'] = array(); + +/** + * List of shortcuts to common commands. + * @var array shortcut => command + */ +$GLOBALS['_PEAR_Command_shortcuts'] = array(); + +/** + * Array of command objects + * @var array class => object + */ +$GLOBALS['_PEAR_Command_objects'] = array(); + +/** + * Which user interface class is being used. + * @var string class name + */ +$GLOBALS['_PEAR_Command_uiclass'] = 'PEAR_Frontend_CLI'; + +/** + * Instance of $_PEAR_Command_uiclass. + * @var object + */ +$GLOBALS['_PEAR_Command_uiobject'] = null; + +/** + * PEAR command class, a simple factory class for administrative + * commands. + * + * How to implement command classes: + * + * - The class must be called PEAR_Command_Nnn, installed in the + * "PEAR/Common" subdir, with a method called getCommands() that + * returns an array of the commands implemented by the class (see + * PEAR/Command/Install.php for an example). + * + * - The class must implement a run() function that is called with three + * params: + * + * (string) command name + * (array) assoc array with options, freely defined by each + * command, for example: + * array('force' => true) + * (array) list of the other parameters + * + * The run() function returns a PEAR_CommandResponse object. Use + * these methods to get information: + * + * int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL) + * *_PARTIAL means that you need to issue at least + * one more command to complete the operation + * (used for example for validation steps). + * + * string getMessage() Returns a message for the user. Remember, + * no HTML or other interface-specific markup. + * + * If something unexpected happens, run() returns a PEAR error. + * + * - DON'T OUTPUT ANYTHING! Return text for output instead. + * + * - DON'T USE HTML! The text you return will be used from both Gtk, + * web and command-line interfaces, so for now, keep everything to + * plain text. + * + * - DON'T USE EXIT OR DIE! Always use pear errors. From static + * classes do PEAR::raiseError(), from other classes do + * $this->raiseError(). + */ +class PEAR_Command +{ + // {{{ factory() + + /** + * Get the right object for executing a command. + * + * @param string $command The name of the command + * @param object $config Instance of PEAR_Config object + * + * @return object the command object or a PEAR error + * + * @access public + * @static + */ + function factory($command, &$config) + { + if (empty($GLOBALS['_PEAR_Command_commandlist'])) { + PEAR_Command::registerCommands(); + } + if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) { + $command = $GLOBALS['_PEAR_Command_shortcuts'][$command]; + } + if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { + return PEAR::raiseError("unknown command `$command'"); + } + $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; + if (!class_exists($class)) { + return PEAR::raiseError("unknown command `$command'"); + } + $ui =& PEAR_Command::getFrontendObject(); + $obj = &new $class($ui, $config); + return $obj; + } + + // }}} + // {{{ & getFrontendObject() + + /** + * Get instance of frontend object. + * + * @return object + * @static + */ + function &getFrontendObject() + { + if (empty($GLOBALS['_PEAR_Command_uiobject'])) { + $GLOBALS['_PEAR_Command_uiobject'] = &new $GLOBALS['_PEAR_Command_uiclass']; + } + return $GLOBALS['_PEAR_Command_uiobject']; + } + + // }}} + // {{{ & setFrontendClass() + + /** + * Load current frontend class. + * + * @param string $uiclass Name of class implementing the frontend + * + * @return object the frontend object, or a PEAR error + * @static + */ + function &setFrontendClass($uiclass) + { + if (is_object($GLOBALS['_PEAR_Command_uiobject']) && + is_a($GLOBALS['_PEAR_Command_uiobject'], $uiclass)) { + return $GLOBALS['_PEAR_Command_uiobject']; + } + if (!class_exists($uiclass)) { + $file = str_replace('_', '/', $uiclass) . '.php'; + if (PEAR_Command::isIncludeable($file)) { + include_once $file; + } + } + if (class_exists($uiclass)) { + $obj = &new $uiclass; + // quick test to see if this class implements a few of the most + // important frontend methods + if (method_exists($obj, 'userConfirm')) { + $GLOBALS['_PEAR_Command_uiobject'] = &$obj; + $GLOBALS['_PEAR_Command_uiclass'] = $uiclass; + return $obj; + } else { + $err = PEAR::raiseError("not a frontend class: $uiclass"); + return $err; + } + } + $err = PEAR::raiseError("no such class: $uiclass"); + return $err; + } + + // }}} + // {{{ setFrontendType() + + // }}} + // {{{ isIncludeable() + + /** + * @param string $path relative or absolute include path + * @return boolean + * @static + */ + function isIncludeable($path) + { + if (file_exists($path) && is_readable($path)) { + return true; + } + $ipath = explode(PATH_SEPARATOR, ini_get('include_path')); + foreach ($ipath as $include) { + $test = realpath($include . DIRECTORY_SEPARATOR . $path); + if (file_exists($test) && is_readable($test)) { + return true; + } + } + return false; + } + + /** + * Set current frontend. + * + * @param string $uitype Name of the frontend type (for example "CLI") + * + * @return object the frontend object, or a PEAR error + * @static + */ + function setFrontendType($uitype) + { + $uiclass = 'PEAR_Frontend_' . $uitype; + return PEAR_Command::setFrontendClass($uiclass); + } + + // }}} + // {{{ registerCommands() + + /** + * Scan through the Command directory looking for classes + * and see what commands they implement. + * + * @param bool (optional) if FALSE (default), the new list of + * commands should replace the current one. If TRUE, + * new entries will be merged with old. + * + * @param string (optional) where (what directory) to look for + * classes, defaults to the Command subdirectory of + * the directory from where this file (__FILE__) is + * included. + * + * @return bool TRUE on success, a PEAR error on failure + * + * @access public + * @static + */ + function registerCommands($merge = false, $dir = null) + { + if ($dir === null) { + $dir = dirname(__FILE__) . '/Command'; + } + $dp = @opendir($dir); + if (empty($dp)) { + return PEAR::raiseError("registerCommands: opendir($dir) failed"); + } + if (!$merge) { + $GLOBALS['_PEAR_Command_commandlist'] = array(); + } + while ($entry = readdir($dp)) { + if ($entry{0} == '.' || substr($entry, -4) != '.php' || $entry == 'Common.php') { + continue; + } + $class = "PEAR_Command_".substr($entry, 0, -4); + $file = "$dir/$entry"; + include_once $file; + // List of commands + if (empty($GLOBALS['_PEAR_Command_objects'][$class])) { + $GLOBALS['_PEAR_Command_objects'][$class] = &new $class($ui, $config); + } + $implements = $GLOBALS['_PEAR_Command_objects'][$class]->getCommands(); + foreach ($implements as $command => $desc) { + $GLOBALS['_PEAR_Command_commandlist'][$command] = $class; + $GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc; + } + $shortcuts = $GLOBALS['_PEAR_Command_objects'][$class]->getShortcuts(); + foreach ($shortcuts as $shortcut => $command) { + $GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command; + } + } + return true; + } + + // }}} + // {{{ getCommands() + + /** + * Get the list of currently supported commands, and what + * classes implement them. + * + * @return array command => implementing class + * + * @access public + * @static + */ + function getCommands() + { + if (empty($GLOBALS['_PEAR_Command_commandlist'])) { + PEAR_Command::registerCommands(); + } + return $GLOBALS['_PEAR_Command_commandlist']; + } + + // }}} + // {{{ getShortcuts() + + /** + * Get the list of command shortcuts. + * + * @return array shortcut => command + * + * @access public + * @static + */ + function getShortcuts() + { + if (empty($GLOBALS['_PEAR_Command_shortcuts'])) { + PEAR_Command::registerCommands(); + } + return $GLOBALS['_PEAR_Command_shortcuts']; + } + + // }}} + // {{{ getGetoptArgs() + + /** + * Compiles arguments for getopt. + * + * @param string $command command to get optstring for + * @param string $short_args (reference) short getopt format + * @param array $long_args (reference) long getopt format + * + * @return void + * + * @access public + * @static + */ + function getGetoptArgs($command, &$short_args, &$long_args) + { + if (empty($GLOBALS['_PEAR_Command_commandlist'])) { + PEAR_Command::registerCommands(); + } + if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) { + return null; + } + $class = $GLOBALS['_PEAR_Command_commandlist'][$command]; + $obj = &$GLOBALS['_PEAR_Command_objects'][$class]; + return $obj->getGetoptArgs($command, $short_args, $long_args); + } + + // }}} + // {{{ getDescription() + + /** + * Get description for a command. + * + * @param string $command Name of the command + * + * @return string command description + * + * @access public + * @static + */ + function getDescription($command) + { + if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) { + return null; + } + return $GLOBALS['_PEAR_Command_commanddesc'][$command]; + } + + // }}} + // {{{ getHelp() + + /** + * Get help for command. + * + * @param string $command Name of the command to return help for + * + * @access public + * @static + */ + function getHelp($command) + { + $cmds = PEAR_Command::getCommands(); + if (isset($cmds[$command])) { + $class = $cmds[$command]; + return $GLOBALS['_PEAR_Command_objects'][$class]->getHelp($command); + } + return false; + } + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Command/Auth.php b/common/PEAR/PEAR/Command/Auth.php new file mode 100644 index 0000000..d6b72db --- /dev/null +++ b/common/PEAR/PEAR/Command/Auth.php @@ -0,0 +1,155 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Auth.php,v 1.10.4.12 2004/01/25 23:19:59 pajoye Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Remote.php"; +require_once "PEAR/Config.php"; + +/** + * PEAR commands for managing configuration data. + * + */ +class PEAR_Command_Auth extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'login' => array( + 'summary' => 'Connects and authenticates to remote server', + 'shortcut' => 'li', + 'function' => 'doLogin', + 'options' => array(), + 'doc' => ' +Log in to the remote server. To use remote functions in the installer +that require any kind of privileges, you need to log in first. The +username and password you enter here will be stored in your per-user +PEAR configuration (~/.pearrc on Unix-like systems). After logging +in, your username and password will be sent along in subsequent +operations on the remote server.', + ), + 'logout' => array( + 'summary' => 'Logs out from the remote server', + 'shortcut' => 'lo', + 'function' => 'doLogout', + 'options' => array(), + 'doc' => ' +Logs out from the remote server. This command does not actually +connect to the remote server, it only deletes the stored username and +password from your user configuration.', + ) + + ); + + // }}} + + // {{{ constructor + + /** + * PEAR_Command_Auth constructor. + * + * @access public + */ + function PEAR_Command_Auth(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doLogin() + + /** + * Execute the 'login' command. + * + * @param string $command command name + * + * @param array $options option_name => value + * + * @param array $params list of additional parameters + * + * @return bool TRUE on success, FALSE for unknown commands, or + * a PEAR error on failure + * + * @access public + */ + function doLogin($command, $options, $params) + { + $server = $this->config->get('master_server'); + $remote = new PEAR_Remote($this->config); + $username = $this->config->get('username'); + if (empty($username)) { + $username = @$_ENV['USER']; + } + $this->ui->outputData("Logging in to $server.", $command); + + list($username, $password) = $this->ui->userDialog( + $command, + array('Username', 'Password'), + array('text', 'password'), + array($username, '') + ); + $username = trim($username); + $password = trim($password); + + $this->config->set('username', $username); + $this->config->set('password', $password); + + $remote->expectError(401); + $ok = $remote->call('logintest'); + $remote->popExpect(); + if ($ok === true) { + $this->ui->outputData("Logged in.", $command); + $this->config->store(); + } else { + return $this->raiseError("Login failed!"); + } + + } + + // }}} + // {{{ doLogout() + + /** + * Execute the 'logout' command. + * + * @param string $command command name + * + * @param array $options option_name => value + * + * @param array $params list of additional parameters + * + * @return bool TRUE on success, FALSE for unknown commands, or + * a PEAR error on failure + * + * @access public + */ + function doLogout($command, $options, $params) + { + $server = $this->config->get('master_server'); + $this->ui->outputData("Logging out from $server.", $command); + $this->config->remove('username'); + $this->config->remove('password'); + $this->config->store(); + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Command/Build.php b/common/PEAR/PEAR/Command/Build.php new file mode 100644 index 0000000..7711bad --- /dev/null +++ b/common/PEAR/PEAR/Command/Build.php @@ -0,0 +1,89 @@ + | +// | Tomas V.V.Cox | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Build.php,v 1.3.4.12 2004/01/25 23:19:59 pajoye Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Builder.php"; + +/** + * PEAR commands for building extensions. + * + */ +class PEAR_Command_Build extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'build' => array( + 'summary' => 'Build an Extension From C Source', + 'function' => 'doBuild', + 'shortcut' => 'b', + 'options' => array(), + 'doc' => '[package.xml] +Builds one or more extensions contained in a package.' + ), + ); + + // }}} + + // {{{ constructor + + /** + * PEAR_Command_Build constructor. + * + * @access public + */ + function PEAR_Command_Build(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doBuild() + + function doBuild($command, $options, $params) + { + if (sizeof($params) < 1) { + $params[0] = 'package.xml'; + } + $builder = &new PEAR_Builder($this->ui); + $this->debug = $this->config->get('verbose'); + $err = $builder->build($params[0], array(&$this, 'buildCallback')); + if (PEAR::isError($err)) { + return $err; + } + return true; + } + + // }}} + // {{{ buildCallback() + + function buildCallback($what, $data) + { + if (($what == 'cmdoutput' && $this->debug > 1) || + ($what == 'output' && $this->debug > 0)) { + $this->ui->outputData(rtrim($data), 'build'); + } + } + + // }}} +} diff --git a/common/PEAR/PEAR/Command/Common.php b/common/PEAR/PEAR/Command/Common.php new file mode 100644 index 0000000..ebdf9bb --- /dev/null +++ b/common/PEAR/PEAR/Command/Common.php @@ -0,0 +1,249 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.19.2.12 2004/01/25 23:19:59 pajoye Exp $ + +require_once "PEAR.php"; + +class PEAR_Command_Common extends PEAR +{ + // {{{ properties + + /** + * PEAR_Config object used to pass user system and configuration + * on when executing commands + * + * @var object + */ + var $config; + + /** + * User Interface object, for all interaction with the user. + * @var object + */ + var $ui; + + var $_deps_rel_trans = array( + 'lt' => '<', + 'le' => '<=', + 'eq' => '=', + 'ne' => '!=', + 'gt' => '>', + 'ge' => '>=', + 'has' => '==' + ); + + var $_deps_type_trans = array( + 'pkg' => 'package', + 'extension' => 'extension', + 'php' => 'PHP', + 'prog' => 'external program', + 'ldlib' => 'external library for linking', + 'rtlib' => 'external runtime library', + 'os' => 'operating system', + 'websrv' => 'web server', + 'sapi' => 'SAPI backend' + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Common constructor. + * + * @access public + */ + function PEAR_Command_Common(&$ui, &$config) + { + parent::PEAR(); + $this->config = &$config; + $this->ui = &$ui; + } + + // }}} + + // {{{ getCommands() + + /** + * Return a list of all the commands defined by this class. + * @return array list of commands + * @access public + */ + function getCommands() + { + $ret = array(); + foreach (array_keys($this->commands) as $command) { + $ret[$command] = $this->commands[$command]['summary']; + } + return $ret; + } + + // }}} + // {{{ getShortcuts() + + /** + * Return a list of all the command shortcuts defined by this class. + * @return array shortcut => command + * @access public + */ + function getShortcuts() + { + $ret = array(); + foreach (array_keys($this->commands) as $command) { + if (isset($this->commands[$command]['shortcut'])) { + $ret[$this->commands[$command]['shortcut']] = $command; + } + } + return $ret; + } + + // }}} + // {{{ getOptions() + + function getOptions($command) + { + return @$this->commands[$command]['options']; + } + + // }}} + // {{{ getGetoptArgs() + + function getGetoptArgs($command, &$short_args, &$long_args) + { + $short_args = ""; + $long_args = array(); + if (empty($this->commands[$command])) { + return; + } + reset($this->commands[$command]); + while (list($option, $info) = each($this->commands[$command]['options'])) { + $larg = $sarg = ''; + if (isset($info['arg'])) { + if ($info['arg']{0} == '(') { + $larg = '=='; + $sarg = '::'; + $arg = substr($info['arg'], 1, -1); + } else { + $larg = '='; + $sarg = ':'; + $arg = $info['arg']; + } + } + if (isset($info['shortopt'])) { + $short_args .= $info['shortopt'] . $sarg; + } + $long_args[] = $option . $larg; + } + } + + // }}} + // {{{ getHelp() + /** + * Returns the help message for the given command + * + * @param string $command The command + * @return mixed A fail string if the command does not have help or + * a two elements array containing [0]=>help string, + * [1]=> help string for the accepted cmd args + */ + function getHelp($command) + { + $config = &PEAR_Config::singleton(); + $help = @$this->commands[$command]['doc']; + if (empty($help)) { + // XXX (cox) Fallback to summary if there is no doc (show both?) + if (!$help = @$this->commands[$command]['summary']) { + return "No help for command \"$command\""; + } + } + if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) { + foreach($matches[0] as $k => $v) { + $help = preg_replace("/$v/", $config->get($matches[1][$k]), $help); + } + } + return array($help, $this->getHelpArgs($command)); + } + + // }}} + // {{{ getHelpArgs() + /** + * Returns the help for the accepted arguments of a command + * + * @param string $command + * @return string The help string + */ + function getHelpArgs($command) + { + if (isset($this->commands[$command]['options']) && + count($this->commands[$command]['options'])) + { + $help = "Options:\n"; + foreach ($this->commands[$command]['options'] as $k => $v) { + if (isset($v['arg'])) { + if ($v['arg']{0} == '(') { + $arg = substr($v['arg'], 1, -1); + $sapp = " [$arg]"; + $lapp = "[=$arg]"; + } else { + $sapp = " $v[arg]"; + $lapp = "=$v[arg]"; + } + } else { + $sapp = $lapp = ""; + } + if (isset($v['shortopt'])) { + $s = $v['shortopt']; + @$help .= " -$s$sapp, --$k$lapp\n"; + } else { + @$help .= " --$k$lapp\n"; + } + $p = " "; + $doc = rtrim(str_replace("\n", "\n$p", $v['doc'])); + $help .= " $doc\n"; + } + return $help; + } + return null; + } + + // }}} + // {{{ run() + + function run($command, $options, $params) + { + $func = @$this->commands[$command]['function']; + if (empty($func)) { + // look for shortcuts + foreach (array_keys($this->commands) as $cmd) { + if (@$this->commands[$cmd]['shortcut'] == $command) { + $command = $cmd; + $func = @$this->commands[$command]['function']; + if (empty($func)) { + return $this->raiseError("unknown command `$command'"); + } + break; + } + } + } + return $this->$func($command, $options, $params); + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Command/Config.php b/common/PEAR/PEAR/Command/Config.php new file mode 100644 index 0000000..93ef533 --- /dev/null +++ b/common/PEAR/PEAR/Command/Config.php @@ -0,0 +1,225 @@ + | +// | Tomas V.V.Cox | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Config.php,v 1.18.4.14 2004/01/25 23:19:59 pajoye Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Config.php"; + +/** + * PEAR commands for managing configuration data. + * + */ +class PEAR_Command_Config extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'config-show' => array( + 'summary' => 'Show All Settings', + 'function' => 'doConfigShow', + 'shortcut' => 'csh', + 'options' => array(), + 'doc' => ' +Displays all configuration values. An optional argument +may be used to tell which configuration layer to display. Valid +configuration layers are "user", "system" and "default". +', + ), + 'config-get' => array( + 'summary' => 'Show One Setting', + 'function' => 'doConfigGet', + 'shortcut' => 'cg', + 'options' => array(), + 'doc' => ' [layer] +Displays the value of one configuration parameter. The +first argument is the name of the parameter, an optional second argument +may be used to tell which configuration layer to look in. Valid configuration +layers are "user", "system" and "default". If no layer is specified, a value +will be picked from the first layer that defines the parameter, in the order +just specified. +', + ), + 'config-set' => array( + 'summary' => 'Change Setting', + 'function' => 'doConfigSet', + 'shortcut' => 'cs', + 'options' => array(), + 'doc' => ' [layer] +Sets the value of one configuration parameter. The first argument is +the name of the parameter, the second argument is the new value. Some +parameters are subject to validation, and the command will fail with +an error message if the new value does not make sense. An optional +third argument may be used to specify in which layer to set the +configuration parameter. The default layer is "user". +', + ), + 'config-help' => array( + 'summary' => 'Show Information About Setting', + 'function' => 'doConfigHelp', + 'shortcut' => 'ch', + 'options' => array(), + 'doc' => '[parameter] +Displays help for a configuration parameter. Without arguments it +displays help for all configuration parameters. +', + ), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Config constructor. + * + * @access public + */ + function PEAR_Command_Config(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doConfigShow() + + function doConfigShow($command, $options, $params) + { + // $params[0] -> the layer + if ($error = $this->_checkLayer(@$params[0])) { + return $this->raiseError($error); + } + $keys = $this->config->getKeys(); + sort($keys); + $data = array('caption' => 'Configuration:'); + foreach ($keys as $key) { + $type = $this->config->getType($key); + $value = $this->config->get($key, @$params[0]); + if ($type == 'password' && $value) { + $value = '********'; + } + if ($value === false) { + $value = 'false'; + } elseif ($value === true) { + $value = 'true'; + } + $data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value); + } + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doConfigGet() + + function doConfigGet($command, $options, $params) + { + // $params[0] -> the parameter + // $params[1] -> the layer + if ($error = $this->_checkLayer(@$params[1])) { + return $this->raiseError($error); + } + if (sizeof($params) < 1 || sizeof($params) > 2) { + return $this->raiseError("config-get expects 1 or 2 parameters"); + } elseif (sizeof($params) == 1) { + $this->ui->outputData("$params[0]=" . $this->config->get($params[0]), $command); + } else { + $data = "$params[1].$params[0]=" .$this->config->get($params[0], $params[1]); + $this->ui->outputData($data, $command); + } + return true; + } + + // }}} + // {{{ doConfigSet() + + function doConfigSet($command, $options, $params) + { + // $param[0] -> a parameter to set + // $param[1] -> the value for the parameter + // $param[2] -> the layer + $failmsg = ''; + if (sizeof($params) < 2 || sizeof($params) > 3) { + $failmsg .= "config-set expects 2 or 3 parameters"; + return PEAR::raiseError($failmsg); + } + if ($error = $this->_checkLayer(@$params[2])) { + $failmsg .= $error; + return PEAR::raiseError($failmsg); + } + if (!call_user_func_array(array(&$this->config, 'set'), $params)) + { + $failmsg = "config-set (" . implode(", ", $params) . ") failed"; + } else { + $this->config->store(); + } + if ($failmsg) { + return $this->raiseError($failmsg); + } + return true; + } + + // }}} + // {{{ doConfigHelp() + + function doConfigHelp($command, $options, $params) + { + if (empty($params)) { + $params = $this->config->getKeys(); + } + $data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : ''); + $data['headline'] = array('Name', 'Type', 'Description'); + $data['border'] = true; + foreach ($params as $name) { + $type = $this->config->getType($name); + $docs = $this->config->getDocs($name); + if ($type == 'set') { + $docs = rtrim($docs) . "\nValid set: " . + implode(' ', $this->config->getSetValues($name)); + } + $data['data'][] = array($name, $type, $docs); + } + $this->ui->outputData($data, $command); + } + + // }}} + // {{{ _checkLayer() + + /** + * Checks if a layer is defined or not + * + * @param string $layer The layer to search for + * @return mixed False on no error or the error message + */ + function _checkLayer($layer = null) + { + if (!empty($layer) && $layer != 'default') { + $layers = $this->config->getLayers(); + if (!in_array($layer, $layers)) { + return " only the layers: \"" . implode('" or "', $layers) . "\" are supported"; + } + } + return false; + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Command/Install.php b/common/PEAR/PEAR/Command/Install.php new file mode 100644 index 0000000..0fb723a --- /dev/null +++ b/common/PEAR/PEAR/Command/Install.php @@ -0,0 +1,465 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Install.php,v 1.38.2.14 2004/01/25 23:19:59 pajoye Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Installer.php"; + +/** + * PEAR commands for installation or deinstallation/upgrading of + * packages. + * + */ +class PEAR_Command_Install extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'install' => array( + 'summary' => 'Install Package', + 'function' => 'doInstall', + 'shortcut' => 'i', + 'options' => array( + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'will overwrite newer installed packages', + ), + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, install anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not install files, only register the package as installed', + ), + 'soft' => array( + 'shortopt' => 's', + 'doc' => 'soft install, fail silently, or upgrade if already installed', + ), + 'nobuild' => array( + 'shortopt' => 'B', + 'doc' => 'don\'t build C extensions', + ), + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'request uncompressed files when downloading', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + 'alldeps' => array( + 'shortopt' => 'a', + 'doc' => 'install all required and optional dependencies', + ), + 'onlyreqdeps' => array( + 'shortopt' => 'o', + 'doc' => 'install all required dependencies', + ), + ), + 'doc' => ' ... +Installs one or more PEAR packages. You can specify a package to +install in four ways: + +"Package-1.0.tgz" : installs from a local file + +"http://example.com/Package-1.0.tgz" : installs from +anywhere on the net. + +"package.xml" : installs the package described in +package.xml. Useful for testing, or for wrapping a PEAR package in +another package manager such as RPM. + +"Package" : queries your configured server +({config master_server}) and downloads the newest package with +the preferred quality/state ({config preferred_state}). + +More than one package may be specified at once. It is ok to mix these +four ways of specifying packages. +'), + 'upgrade' => array( + 'summary' => 'Upgrade Package', + 'function' => 'doInstall', + 'shortcut' => 'up', + 'options' => array( + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'overwrite newer installed packages', + ), + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, upgrade anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not install files, only register the package as upgraded', + ), + 'nobuild' => array( + 'shortopt' => 'B', + 'doc' => 'don\'t build C extensions', + ), + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'request uncompressed files when downloading', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + 'alldeps' => array( + 'shortopt' => 'a', + 'doc' => 'install all required and optional dependencies', + ), + 'onlyreqdeps' => array( + 'shortopt' => 'o', + 'doc' => 'install all required dependencies', + ), + ), + 'doc' => ' ... +Upgrades one or more PEAR packages. See documentation for the +"install" command for ways to specify a package. + +When upgrading, your package will be updated if the provided new +package has a higher version number (use the -f option if you need to +upgrade anyway). + +More than one package may be specified at once. +'), + 'upgrade-all' => array( + 'summary' => 'Upgrade All Packages', + 'function' => 'doInstall', + 'shortcut' => 'ua', + 'options' => array( + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, upgrade anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not install files, only register the package as upgraded', + ), + 'nobuild' => array( + 'shortopt' => 'B', + 'doc' => 'don\'t build C extensions', + ), + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'request uncompressed files when downloading', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + ), + 'doc' => ' +Upgrades all packages that have a newer release available. Upgrades are +done only if there is a release available of the state specified in +"preferred_state" (currently {config preferred_state}), or a state considered +more stable. +'), + 'uninstall' => array( + 'summary' => 'Un-install Package', + 'function' => 'doUninstall', + 'shortcut' => 'un', + 'options' => array( + 'nodeps' => array( + 'shortopt' => 'n', + 'doc' => 'ignore dependencies, uninstall anyway', + ), + 'register-only' => array( + 'shortopt' => 'r', + 'doc' => 'do not remove files, only register the packages as not installed', + ), + 'installroot' => array( + 'shortopt' => 'R', + 'arg' => 'DIR', + 'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)', + ), + 'ignore-errors' => array( + 'doc' => 'force install even if there were errors', + ), + ), + 'doc' => ' ... +Uninstalls one or more PEAR packages. More than one package may be +specified at once. +'), + 'bundle' => array( + 'summary' => 'Unpacks a Pecl Package', + 'function' => 'doBundle', + 'shortcut' => 'bun', + 'options' => array( + 'destination' => array( + 'shortopt' => 'd', + 'arg' => 'DIR', + 'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)', + ), + 'force' => array( + 'shortopt' => 'f', + 'doc' => 'Force the unpacking even if there were errors in the package', + ), + ), + 'doc' => ' +Unpacks a Pecl Package into the selected location. It will download the +package if needed. +'), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Install constructor. + * + * @access public + */ + function PEAR_Command_Install(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doInstall() + + function doInstall($command, $options, $params) + { + require_once 'PEAR/Downloader.php'; + if (empty($this->installer)) { + $this->installer = &new PEAR_Installer($this->ui); + } + if ($command == 'upgrade') { + $options['upgrade'] = true; + } + if ($command == 'upgrade-all') { + include_once "PEAR/Remote.php"; + $options['upgrade'] = true; + $remote = &new PEAR_Remote($this->config); + $state = $this->config->get('preferred_state'); + if (empty($state) || $state == 'any') { + $latest = $remote->call("package.listLatestReleases"); + } else { + $latest = $remote->call("package.listLatestReleases", $state); + } + if (PEAR::isError($latest)) { + return $latest; + } + $reg = new PEAR_Registry($this->config->get('php_dir')); + $installed = array_flip($reg->listPackages()); + $params = array(); + foreach ($latest as $package => $info) { + $package = strtolower($package); + if (!isset($installed[$package])) { + // skip packages we don't have installed + continue; + } + $inst_version = $reg->packageInfo($package, 'version'); + if (version_compare("$info[version]", "$inst_version", "le")) { + // installed version is up-to-date + continue; + } + $params[] = $package; + $this->ui->outputData(array('data' => "Will upgrade $package"), $command); + } + } + $this->downloader = &new PEAR_Downloader($this->ui, $options, $this->config); + $errors = array(); + $downloaded = array(); + $this->downloader->download($params); + $errors = $this->downloader->getErrorMsgs(); + if (count($errors)) { + $err['data'] = array($errors); + $err['headline'] = 'Install Errors'; + $this->ui->outputData($err); + return $this->raiseError("$command failed"); + } + $downloaded = $this->downloader->getDownloadedPackages(); + $this->installer->sortPkgDeps($downloaded); + foreach ($downloaded as $pkg) { + $bn = basename($pkg['file']); + $info = $this->installer->install($pkg['file'], $options, $this->config); + if (is_array($info)) { + if ($this->config->get('verbose') > 0) { + $label = "$info[package] $info[version]"; + $out = array('data' => "$command ok: $label"); + if (isset($info['release_warnings'])) { + $out['release_warnings'] = $info['release_warnings']; + } + $this->ui->outputData($out, $command); + } + } else { + return $this->raiseError("$command failed"); + } + } + return true; + } + + // }}} + // {{{ doUninstall() + + function doUninstall($command, $options, $params) + { + if (empty($this->installer)) { + $this->installer = &new PEAR_Installer($this->ui); + } + if (sizeof($params) < 1) { + return $this->raiseError("Please supply the package(s) you want to uninstall"); + } + include_once 'PEAR/Registry.php'; + $reg = new PEAR_Registry($this->config->get('php_dir')); + $newparams = array(); + $badparams = array(); + foreach ($params as $pkg) { + $info = $reg->packageInfo($pkg); + if ($info === null) { + $badparams[] = $pkg; + } else { + $newparams[] = $info; + } + } + $this->installer->sortPkgDeps($newparams, true); + $params = array(); + foreach($newparams as $info) { + $params[] = $info['info']['package']; + } + $params = array_merge($params, $badparams); + foreach ($params as $pkg) { + if ($this->installer->uninstall($pkg, $options)) { + if ($this->config->get('verbose') > 0) { + $this->ui->outputData("uninstall ok: $pkg", $command); + } + } else { + return $this->raiseError("uninstall failed: $pkg"); + } + } + return true; + } + + // }}} + + + // }}} + // {{{ doBundle() + /* + (cox) It just downloads and untars the package, does not do + any check that the PEAR_Installer::_installFile() does. + */ + + function doBundle($command, $options, $params) + { + if (empty($this->installer)) { + $this->installer = &new PEAR_Downloader($this->ui); + } + $installer = &$this->installer; + if (sizeof($params) < 1) { + return $this->raiseError("Please supply the package you want to bundle"); + } + $pkgfile = $params[0]; + $need_download = false; + if (preg_match('#^(http|ftp)://#', $pkgfile)) { + $need_download = true; + } elseif (!@is_file($pkgfile)) { + if ($installer->validPackageName($pkgfile)) { + $pkgfile = $installer->getPackageDownloadUrl($pkgfile); + $need_download = true; + } else { + if (strlen($pkgfile)) { + return $this->raiseError("Could not open the package file: $pkgfile"); + } else { + return $this->raiseError("No package file given"); + } + } + } + + // Download package ----------------------------------------------- + if ($need_download) { + $downloaddir = $installer->config->get('download_dir'); + if (empty($downloaddir)) { + if (PEAR::isError($downloaddir = System::mktemp('-d'))) { + return $downloaddir; + } + $installer->log(2, '+ tmp dir created at ' . $downloaddir); + } + $callback = $this->ui ? array(&$installer, '_downloadCallback') : null; + $file = $installer->downloadHttp($pkgfile, $this->ui, $downloaddir, $callback); + if (PEAR::isError($file)) { + return $this->raiseError($file); + } + $pkgfile = $file; + } + + // Parse xml file ----------------------------------------------- + $pkginfo = $installer->infoFromTgzFile($pkgfile); + if (PEAR::isError($pkginfo)) { + return $this->raiseError($pkginfo); + } + $installer->validatePackageInfo($pkginfo, $errors, $warnings); + // XXX We allow warnings, do we have to do it? + if (count($errors)) { + if (empty($options['force'])) { + return $this->raiseError("The following errors where found:\n". + implode("\n", $errors)); + } else { + $this->log(0, "warning : the following errors were found:\n". + implode("\n", $errors)); + } + } + $pkgname = $pkginfo['package']; + + // Unpacking ------------------------------------------------- + + if (isset($options['destination'])) { + if (!is_dir($options['destination'])) { + System::mkdir('-p ' . $options['destination']); + } + $dest = realpath($options['destination']); + } else { + $pwd = getcwd(); + if (is_dir($pwd . DIRECTORY_SEPARATOR . 'ext')) { + $dest = $pwd . DIRECTORY_SEPARATOR . 'ext'; + } else { + $dest = $pwd; + } + } + $dest .= DIRECTORY_SEPARATOR . $pkgname; + $orig = $pkgname . '-' . $pkginfo['version']; + + $tar = new Archive_Tar($pkgfile); + if (!@$tar->extractModify($dest, $orig)) { + return $this->raiseError("unable to unpack $pkgfile"); + } + $this->ui->outputData("Package ready at '$dest'"); + // }}} + } + + // }}} + +} +?> diff --git a/common/PEAR/PEAR/Command/Mirror.php b/common/PEAR/PEAR/Command/Mirror.php new file mode 100644 index 0000000..593081d --- /dev/null +++ b/common/PEAR/PEAR/Command/Mirror.php @@ -0,0 +1,99 @@ + | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Mirror.php,v 1.2.2.4 2004/01/25 23:19:59 pajoye Exp $ + +require_once "PEAR/Command/Common.php"; +require_once "PEAR/Command.php"; +require_once "PEAR/Remote.php"; +require_once "PEAR.php"; + +/** + * PEAR commands for providing file mirrors + * + */ +class PEAR_Command_Mirror extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'download-all' => array( + 'summary' => 'Downloads each avaible Package from master_server', + 'function' => 'doDownloadAll', + 'shortcut' => 'da', + 'options' => array(), + 'doc' => ' + Request a list of avaible Packages from the Package-Server + (master_server) and downloads them to current working dir' + ), + ); + + // }}} + + // {{{ constructor + + /** + * PEAR_Command_Mirror constructor. + * + * @access public + * @param object PEAR_Frontend a reference to an frontend + * @param object PEAR_Config a reference to the configuration data + */ + function PEAR_Command_Mirror(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doDownloadAll() + /** + * retrieves a list of avaible Packages from master server + * and downloads them + * + * @access public + * @param string $command the command + * @param array $options the command options before the command + * @param array $params the stuff after the command name + * @return bool true if succesful + * @throw PEAR_Error + */ + function doDownloadAll($command, $options, $params) + { + $this->config->set("php_dir", "."); + $remote = &new PEAR_Remote($this->config); + $remoteInfo = $remote->call("package.listAll"); + if(PEAR::isError($remoteInfo)) { + return $remoteInfo; + } + $cmd = &PEAR_Command::factory("download", $this->config); + if(PEAR::isError($cmd)) { + return $cmd; + } + foreach($remoteInfo as $pkgn=>$pkg) { + // error handling not neccesary, because + // already done by the download command + $cmd->run("download", array(), array($pkgn)); + } + + return true; + } + + // }}} +} diff --git a/common/PEAR/PEAR/Command/Package.php b/common/PEAR/PEAR/Command/Package.php new file mode 100644 index 0000000..5dbe7d6 --- /dev/null +++ b/common/PEAR/PEAR/Command/Package.php @@ -0,0 +1,722 @@ + | +// | Martin Jansen | +// +----------------------------------------------------------------------+ +// +// $Id: Package.php,v 1.42.2.17 2004/06/08 18:26:32 cellog Exp $ + +require_once 'PEAR/Common.php'; +require_once 'PEAR/Command/Common.php'; + +class PEAR_Command_Package extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'package' => array( + 'summary' => 'Build Package', + 'function' => 'doPackage', + 'shortcut' => 'p', + 'options' => array( + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'Do not gzip the package file' + ), + 'showname' => array( + 'shortopt' => 'n', + 'doc' => 'Print the name of the packaged file.', + ), + ), + 'doc' => '[descfile] +Creates a PEAR package from its description file (usually called +package.xml). +' + ), + 'package-validate' => array( + 'summary' => 'Validate Package Consistency', + 'function' => 'doPackageValidate', + 'shortcut' => 'pv', + 'options' => array(), + 'doc' => ' +', + ), + 'cvsdiff' => array( + 'summary' => 'Run a "cvs diff" for all files in a package', + 'function' => 'doCvsDiff', + 'shortcut' => 'cd', + 'options' => array( + 'quiet' => array( + 'shortopt' => 'q', + 'doc' => 'Be quiet', + ), + 'reallyquiet' => array( + 'shortopt' => 'Q', + 'doc' => 'Be really quiet', + ), + 'date' => array( + 'shortopt' => 'D', + 'doc' => 'Diff against revision of DATE', + 'arg' => 'DATE', + ), + 'release' => array( + 'shortopt' => 'R', + 'doc' => 'Diff against tag for package release REL', + 'arg' => 'REL', + ), + 'revision' => array( + 'shortopt' => 'r', + 'doc' => 'Diff against revision REV', + 'arg' => 'REV', + ), + 'context' => array( + 'shortopt' => 'c', + 'doc' => 'Generate context diff', + ), + 'unified' => array( + 'shortopt' => 'u', + 'doc' => 'Generate unified diff', + ), + 'ignore-case' => array( + 'shortopt' => 'i', + 'doc' => 'Ignore case, consider upper- and lower-case letters equivalent', + ), + 'ignore-whitespace' => array( + 'shortopt' => 'b', + 'doc' => 'Ignore changes in amount of white space', + ), + 'ignore-blank-lines' => array( + 'shortopt' => 'B', + 'doc' => 'Ignore changes that insert or delete blank lines', + ), + 'brief' => array( + 'doc' => 'Report only whether the files differ, no details', + ), + 'dry-run' => array( + 'shortopt' => 'n', + 'doc' => 'Don\'t do anything, just pretend', + ), + ), + 'doc' => ' +Compares all the files in a package. Without any options, this +command will compare the current code with the last checked-in code. +Using the -r or -R option you may compare the current code with that +of a specific release. +', + ), + 'cvstag' => array( + 'summary' => 'Set CVS Release Tag', + 'function' => 'doCvsTag', + 'shortcut' => 'ct', + 'options' => array( + 'quiet' => array( + 'shortopt' => 'q', + 'doc' => 'Be quiet', + ), + 'reallyquiet' => array( + 'shortopt' => 'Q', + 'doc' => 'Be really quiet', + ), + 'slide' => array( + 'shortopt' => 'F', + 'doc' => 'Move (slide) tag if it exists', + ), + 'delete' => array( + 'shortopt' => 'd', + 'doc' => 'Remove tag', + ), + 'dry-run' => array( + 'shortopt' => 'n', + 'doc' => 'Don\'t do anything, just pretend', + ), + ), + 'doc' => ' +Sets a CVS tag on all files in a package. Use this command after you have +packaged a distribution tarball with the "package" command to tag what +revisions of what files were in that release. If need to fix something +after running cvstag once, but before the tarball is released to the public, +use the "slide" option to move the release tag. +', + ), + 'run-tests' => array( + 'summary' => 'Run Regression Tests', + 'function' => 'doRunTests', + 'shortcut' => 'rt', + 'options' => array(), + 'doc' => '[testfile|dir ...] +Run regression tests with PHP\'s regression testing script (run-tests.php).', + ), + 'package-dependencies' => array( + 'summary' => 'Show package dependencies', + 'function' => 'doPackageDependencies', + 'shortcut' => 'pd', + 'options' => array(), + 'doc' => ' +List all depencies the package has.' + ), + 'sign' => array( + 'summary' => 'Sign a package distribution file', + 'function' => 'doSign', + 'shortcut' => 'si', + 'options' => array(), + 'doc' => ' +Signs a package distribution (.tar or .tgz) file with GnuPG.', + ), + 'makerpm' => array( + 'summary' => 'Builds an RPM spec file from a PEAR package', + 'function' => 'doMakeRPM', + 'shortcut' => 'rpm', + 'options' => array( + 'spec-template' => array( + 'shortopt' => 't', + 'arg' => 'FILE', + 'doc' => 'Use FILE as RPM spec file template' + ), + 'rpm-pkgname' => array( + 'shortopt' => 'p', + 'arg' => 'FORMAT', + 'doc' => 'Use FORMAT as format string for RPM package name, %s is replaced +by the PEAR package name, defaults to "PEAR::%s".', + ), + ), + 'doc' => ' + +Creates an RPM .spec file for wrapping a PEAR package inside an RPM +package. Intended to be used from the SPECS directory, with the PEAR +package tarball in the SOURCES directory: + +$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz +Wrote RPM spec file PEAR::Net_Geo-1.0.spec +$ rpm -bb PEAR::Net_Socket-1.0.spec +... +Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm +', + ), + ); + + var $output; + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Package constructor. + * + * @access public + */ + function PEAR_Command_Package(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ _displayValidationResults() + + function _displayValidationResults($err, $warn, $strict = false) + { + foreach ($err as $e) { + $this->output .= "Error: $e\n"; + } + foreach ($warn as $w) { + $this->output .= "Warning: $w\n"; + } + $this->output .= sprintf('Validation: %d error(s), %d warning(s)'."\n", + sizeof($err), sizeof($warn)); + if ($strict && sizeof($err) > 0) { + $this->output .= "Fix these errors and try again."; + return false; + } + return true; + } + + // }}} + // {{{ doPackage() + + function doPackage($command, $options, $params) + { + $this->output = ''; + include_once 'PEAR/Packager.php'; + $pkginfofile = isset($params[0]) ? $params[0] : 'package.xml'; + $packager =& new PEAR_Packager(); + $err = $warn = array(); + $dir = dirname($pkginfofile); + $compress = empty($options['nocompress']) ? true : false; + $result = $packager->package($pkginfofile, $compress); + if (PEAR::isError($result)) { + $this->ui->outputData($this->output, $command); + return $this->raiseError($result); + } + // Don't want output, only the package file name just created + if (isset($options['showname'])) { + $this->output = $result; + } + /* (cox) What is supposed to do that code? + $lines = explode("\n", $this->output); + foreach ($lines as $line) { + $this->output .= $line."n"; + } + */ + if (PEAR::isError($result)) { + $this->output .= "Package failed: ".$result->getMessage(); + } + $this->ui->outputData($this->output, $command); + return true; + } + + // }}} + // {{{ doPackageValidate() + + function doPackageValidate($command, $options, $params) + { + $this->output = ''; + if (sizeof($params) < 1) { + $params[0] = "package.xml"; + } + $obj = new PEAR_Common; + $info = null; + if ($fp = @fopen($params[0], "r")) { + $test = fread($fp, 5); + fclose($fp); + if ($test == "infoFromDescriptionFile($params[0]); + } + } + if (empty($info)) { + $info = $obj->infoFromTgzFile($params[0]); + } + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $obj->validatePackageInfo($info, $err, $warn); + $this->_displayValidationResults($err, $warn); + $this->ui->outputData($this->output, $command); + return true; + } + + // }}} + // {{{ doCvsTag() + + function doCvsTag($command, $options, $params) + { + $this->output = ''; + $_cmd = $command; + if (sizeof($params) < 1) { + $help = $this->getHelp($command); + return $this->raiseError("$command: missing parameter: $help[0]"); + } + $obj = new PEAR_Common; + $info = $obj->infoFromDescriptionFile($params[0]); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $err = $warn = array(); + $obj->validatePackageInfo($info, $err, $warn); + if (!$this->_displayValidationResults($err, $warn, true)) { + $this->ui->outputData($this->output, $command); + break; + } + $version = $info['version']; + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $version); + $cvstag = "RELEASE_$cvsversion"; + $files = array_keys($info['filelist']); + $command = "cvs"; + if (isset($options['quiet'])) { + $command .= ' -q'; + } + if (isset($options['reallyquiet'])) { + $command .= ' -Q'; + } + $command .= ' tag'; + if (isset($options['slide'])) { + $command .= ' -F'; + } + if (isset($options['delete'])) { + $command .= ' -d'; + } + $command .= ' ' . $cvstag . ' ' . escapeshellarg($params[0]); + foreach ($files as $file) { + $command .= ' ' . escapeshellarg($file); + } + if ($this->config->get('verbose') > 1) { + $this->output .= "+ $command\n"; + } + $this->output .= "+ $command\n"; + if (empty($options['dry-run'])) { + $fp = popen($command, "r"); + while ($line = fgets($fp, 1024)) { + $this->output .= rtrim($line)."\n"; + } + pclose($fp); + } + $this->ui->outputData($this->output, $_cmd); + return true; + } + + // }}} + // {{{ doCvsDiff() + + function doCvsDiff($command, $options, $params) + { + $this->output = ''; + if (sizeof($params) < 1) { + $help = $this->getHelp($command); + return $this->raiseError("$command: missing parameter: $help[0]"); + } + $obj = new PEAR_Common; + $info = $obj->infoFromDescriptionFile($params[0]); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + $files = array_keys($info['filelist']); + $cmd = "cvs"; + if (isset($options['quiet'])) { + $cmd .= ' -q'; + unset($options['quiet']); + } + if (isset($options['reallyquiet'])) { + $cmd .= ' -Q'; + unset($options['reallyquiet']); + } + if (isset($options['release'])) { + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $options['release']); + $cvstag = "RELEASE_$cvsversion"; + $options['revision'] = $cvstag; + unset($options['release']); + } + $execute = true; + if (isset($options['dry-run'])) { + $execute = false; + unset($options['dry-run']); + } + $cmd .= ' diff'; + // the rest of the options are passed right on to "cvs diff" + foreach ($options as $option => $optarg) { + $arg = @$this->commands[$command]['options'][$option]['arg']; + $short = @$this->commands[$command]['options'][$option]['shortopt']; + $cmd .= $short ? " -$short" : " --$option"; + if ($arg && $optarg) { + $cmd .= ($short ? '' : '=') . escapeshellarg($optarg); + } + } + foreach ($files as $file) { + $cmd .= ' ' . escapeshellarg($file); + } + if ($this->config->get('verbose') > 1) { + $this->output .= "+ $cmd\n"; + } + if ($execute) { + $fp = popen($cmd, "r"); + while ($line = fgets($fp, 1024)) { + $this->output .= rtrim($line)."\n"; + } + pclose($fp); + } + $this->ui->outputData($this->output, $command); + return true; + } + + // }}} + // {{{ doRunTests() + + function doRunTests($command, $options, $params) + { + $cwd = getcwd(); + $php = $this->config->get('php_bin'); + putenv("TEST_PHP_EXECUTABLE=$php"); + // all core PEAR tests use this constant to determine whether they should be run or not + putenv("PHP_PEAR_RUNTESTS=1"); + $ip = ini_get("include_path"); + $ps = OS_WINDOWS ? ';' : ':'; + $run_tests = $rtsts = $this->config->get('php_dir') . DIRECTORY_SEPARATOR . 'run-tests.php'; + if (!file_exists($run_tests)) { + $run_tests = PEAR_INSTALL_DIR . DIRECTORY_SEPARATOR . 'run-tests.php'; + if (!file_exists($run_tests)) { + return $this->raiseError("No run-tests.php file found. Please copy this ". + "file from the sources of your PHP distribution to $rtsts"); + } + } + if (OS_WINDOWS) { + // note, this requires a slightly modified version of run-tests.php + // for some setups + // unofficial download location is in the pear-dev archives + $argv = $params; + array_unshift($argv, $run_tests); + $argc = count($argv); + include $run_tests; + } else { + $plist = implode(' ', $params); + $cmd = "$php -d include_path=$cwd$ps$ip -f $run_tests -- $plist"; + system($cmd); + } + return true; + } + + // }}} + // {{{ doPackageDependencies() + + function doPackageDependencies($command, $options, $params) + { + // $params[0] -> the PEAR package to list its information + if (sizeof($params) != 1) { + return $this->raiseError("bad parameter(s), try \"help $command\""); + } + + $obj = new PEAR_Common(); + if (PEAR::isError($info = $obj->infoFromAny($params[0]))) { + return $this->raiseError($info); + } + + if (is_array($info['release_deps'])) { + $data = array( + 'caption' => 'Dependencies for ' . $info['package'], + 'border' => true, + 'headline' => array("Type", "Name", "Relation", "Version"), + ); + + foreach ($info['release_deps'] as $d) { + + if (isset($this->_deps_rel_trans[$d['rel']])) { + $rel = $this->_deps_rel_trans[$d['rel']]; + } else { + $rel = $d['rel']; + } + + if (isset($this->_deps_type_trans[$d['type']])) { + $type = ucfirst($this->_deps_type_trans[$d['type']]); + } else { + $type = $d['type']; + } + + if (isset($d['name'])) { + $name = $d['name']; + } else { + $name = ''; + } + + if (isset($d['version'])) { + $version = $d['version']; + } else { + $version = ''; + } + + $data['data'][] = array($type, $name, $rel, $version); + } + + $this->ui->outputData($data, $command); + return true; + } + + // Fallback + $this->ui->outputData("This package does not have any dependencies.", $command); + } + + // }}} + // {{{ doSign() + + function doSign($command, $options, $params) + { + // should move most of this code into PEAR_Packager + // so it'll be easy to implement "pear package --sign" + if (sizeof($params) != 1) { + return $this->raiseError("bad parameter(s), try \"help $command\""); + } + if (!file_exists($params[0])) { + return $this->raiseError("file does not exist: $params[0]"); + } + $obj = new PEAR_Common; + $info = $obj->infoFromTgzFile($params[0]); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + include_once "Archive/Tar.php"; + include_once "System.php"; + $tar = new Archive_Tar($params[0]); + $tmpdir = System::mktemp('-d pearsign'); + if (!$tar->extractList('package.xml package.sig', $tmpdir)) { + return $this->raiseError("failed to extract tar file"); + } + if (file_exists("$tmpdir/package.sig")) { + return $this->raiseError("package already signed"); + } + @unlink("$tmpdir/package.sig"); + $input = $this->ui->userDialog($command, + array('GnuPG Passphrase'), + array('password')); + $gpg = popen("gpg --batch --passphrase-fd 0 --armor --detach-sign --output $tmpdir/package.sig $tmpdir/package.xml 2>/dev/null", "w"); + if (!$gpg) { + return $this->raiseError("gpg command failed"); + } + fwrite($gpg, "$input[0]\r"); + if (pclose($gpg) || !file_exists("$tmpdir/package.sig")) { + return $this->raiseError("gpg sign failed"); + } + $tar->addModify("$tmpdir/package.sig", '', $tmpdir); + return true; + } + + // }}} + // {{{ doMakeRPM() + + /* + + (cox) + + TODO: + + - Fill the rpm dependencies in the template file. + + IDEAS: + + - Instead of mapping the role to rpm vars, perhaps it's better + + to use directly the pear cmd to install the files by itself + + in %postrun so: + + pear -d php_dir=%{_libdir}/php/pear -d test_dir=.. + + */ + + function doMakeRPM($command, $options, $params) + { + if (sizeof($params) != 1) { + return $this->raiseError("bad parameter(s), try \"help $command\""); + } + if (!file_exists($params[0])) { + return $this->raiseError("file does not exist: $params[0]"); + } + include_once "Archive/Tar.php"; + include_once "PEAR/Installer.php"; + include_once "System.php"; + $tar = new Archive_Tar($params[0]); + $tmpdir = System::mktemp('-d pear2rpm'); + $instroot = System::mktemp('-d pear2rpm'); + $tmp = $this->config->get('verbose'); + $this->config->set('verbose', 0); + $installer = new PEAR_Installer($this->ui); + $info = $installer->install($params[0], + array('installroot' => $instroot, + 'nodeps' => true)); + $pkgdir = "$info[package]-$info[version]"; + $info['rpm_xml_dir'] = '/var/lib/pear'; + $this->config->set('verbose', $tmp); + if (!$tar->extractList("package.xml", $tmpdir, $pkgdir)) { + return $this->raiseError("failed to extract $params[0]"); + } + if (!file_exists("$tmpdir/package.xml")) { + return $this->raiseError("no package.xml found in $params[0]"); + } + if (isset($options['spec-template'])) { + $spec_template = $options['spec-template']; + } else { + $spec_template = $this->config->get('data_dir') . + '/PEAR/template.spec'; + } + if (isset($options['rpm-pkgname'])) { + $rpm_pkgname_format = $options['rpm-pkgname']; + } else { + $rpm_pkgname_format = "PEAR::%s"; + } + + $info['extra_headers'] = ''; + $info['doc_files'] = ''; + $info['files'] = ''; + $info['rpm_package'] = sprintf($rpm_pkgname_format, $info['package']); + $srcfiles = 0; + foreach ($info['filelist'] as $name => $attr) { + + if (!isset($attr['role'])) { + continue; + } + if ($attr['role'] == 'doc') { + $info['doc_files'] .= " $name"; + + // Map role to the rpm vars + } else { + + $c_prefix = '%{_libdir}/php/pear'; + + switch ($attr['role']) { + + case 'php': + + $prefix = $c_prefix; break; + + case 'ext': + + $prefix = '%{_libdir}/php'; break; // XXX good place? + + case 'src': + + $srcfiles++; + + $prefix = '%{_includedir}/php'; break; // XXX good place? + + case 'test': + + $prefix = "$c_prefix/tests/" . $info['package']; break; + + case 'data': + + $prefix = "$c_prefix/data/" . $info['package']; break; + + case 'script': + + $prefix = '%{_bindir}'; break; + + } + + $name = str_replace('\\', '/', $name); + $info['files'] .= "$prefix/$name\n"; + + } + } + if ($srcfiles > 0) { + include_once "OS/Guess.php"; + $os = new OS_Guess; + $arch = $os->getCpu(); + } else { + $arch = 'noarch'; + } + $cfg = array('master_server', 'php_dir', 'ext_dir', 'doc_dir', + 'bin_dir', 'data_dir', 'test_dir'); + foreach ($cfg as $k) { + $info[$k] = $this->config->get($k); + } + $info['arch'] = $arch; + $fp = @fopen($spec_template, "r"); + if (!$fp) { + return $this->raiseError("could not open RPM spec file template $spec_template: $php_errormsg"); + } + $spec_contents = preg_replace('/@([a-z0-9_-]+)@/e', '$info["\1"]', fread($fp, filesize($spec_template))); + fclose($fp); + $spec_file = "$info[rpm_package]-$info[version].spec"; + $wp = fopen($spec_file, "wb"); + if (!$wp) { + return $this->raiseError("could not write RPM spec file $spec_file: $php_errormsg"); + } + fwrite($wp, $spec_contents); + fclose($wp); + $this->ui->outputData("Wrote RPM spec file $spec_file", $command); + + return true; + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Command/Registry.php b/common/PEAR/PEAR/Command/Registry.php new file mode 100644 index 0000000..278f42b --- /dev/null +++ b/common/PEAR/PEAR/Command/Registry.php @@ -0,0 +1,351 @@ + | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Registry.php,v 1.24.4.13 2003/10/20 15:51:45 cox Exp $ + +require_once 'PEAR/Command/Common.php'; +require_once 'PEAR/Registry.php'; +require_once 'PEAR/Config.php'; + +class PEAR_Command_Registry extends PEAR_Command_Common +{ + // {{{ properties + + var $commands = array( + 'list' => array( + 'summary' => 'List Installed Packages', + 'function' => 'doList', + 'shortcut' => 'l', + 'options' => array(), + 'doc' => '[package] +If invoked without parameters, this command lists the PEAR packages +installed in your php_dir ({config php_dir)). With a parameter, it +lists the files in that package. +', + ), + 'shell-test' => array( + 'summary' => 'Shell Script Test', + 'function' => 'doShellTest', + 'shortcut' => 'st', + 'options' => array(), + 'doc' => ' [[relation] version] +Tests if a package is installed in the system. Will exit(1) if it is not. + The version comparison operator. One of: + <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne + The version to compare with +'), + 'info' => array( + 'summary' => 'Display information about a package', + 'function' => 'doInfo', + 'shortcut' => 'in', + 'options' => array(), + 'doc' => ' +Displays information about a package. The package argument may be a +local package file, an URL to a package file, or the name of an +installed package.' + ) + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Registry constructor. + * + * @access public + */ + function PEAR_Command_Registry(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doList() + + function _sortinfo($a, $b) + { + return strcmp($a['package'], $b['package']); + } + + function doList($command, $options, $params) + { + $reg = new PEAR_Registry($this->config->get('php_dir')); + if (sizeof($params) == 0) { + $installed = $reg->packageInfo(); + usort($installed, array(&$this, '_sortinfo')); + $i = $j = 0; + $data = array( + 'caption' => 'Installed packages:', + 'border' => true, + 'headline' => array('Package', 'Version', 'State') + ); + foreach ($installed as $package) { + $data['data'][] = array($package['package'], + $package['version'], + @$package['release_state']); + } + if (count($installed)==0) { + $data = '(no packages installed)'; + } + $this->ui->outputData($data, $command); + } else { + if (file_exists($params[0]) && !is_dir($params[0])) { + include_once "PEAR/Common.php"; + $obj = &new PEAR_Common; + $info = $obj->infoFromAny($params[0]); + $headings = array('Package File', 'Install Path'); + $installed = false; + } else { + $info = $reg->packageInfo($params[0]); + $headings = array('Type', 'Install Path'); + $installed = true; + } + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + if ($info === null) { + return $this->raiseError("`$params[0]' not installed"); + } + $list = $info['filelist']; + if ($installed) { + $caption = 'Installed Files For ' . $params[0]; + } else { + $caption = 'Contents of ' . basename($params[0]); + } + $data = array( + 'caption' => $caption, + 'border' => true, + 'headline' => $headings); + foreach ($list as $file => $att) { + if ($installed) { + if (empty($att['installed_as'])) { + continue; + } + $data['data'][] = array($att['role'], $att['installed_as']); + } else { + if (isset($att['baseinstalldir'])) { + $dest = $att['baseinstalldir'] . DIRECTORY_SEPARATOR . + $file; + } else { + $dest = $file; + } + switch ($att['role']) { + case 'test': + case 'data': + if ($installed) { + break 2; + } + $dest = '-- will not be installed --'; + break; + case 'doc': + $dest = $this->config->get('doc_dir') . DIRECTORY_SEPARATOR . + $dest; + break; + case 'php': + default: + $dest = $this->config->get('php_dir') . DIRECTORY_SEPARATOR . + $dest; + } + $dest = preg_replace('!/+!', '/', $dest); + $file = preg_replace('!/+!', '/', $file); + $data['data'][] = array($file, $dest); + } + } + $this->ui->outputData($data, $command); + + + } + return true; + } + + // }}} + // {{{ doShellTest() + + function doShellTest($command, $options, $params) + { + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $reg = &new PEAR_Registry($this->config->get('php_dir')); + // "pear shell-test Foo" + if (sizeof($params) == 1) { + if (!$reg->packageExists($params[0])) { + exit(1); + } + // "pear shell-test Foo 1.0" + } elseif (sizeof($params) == 2) { + $v = $reg->packageInfo($params[0], 'version'); + if (!$v || !version_compare("$v", "{$params[1]}", "ge")) { + exit(1); + } + // "pear shell-test Foo ge 1.0" + } elseif (sizeof($params) == 3) { + $v = $reg->packageInfo($params[0], 'version'); + if (!$v || !version_compare("$v", "{$params[2]}", $params[1])) { + exit(1); + } + } else { + $this->popErrorHandling(); + $this->raiseError("$command: expects 1 to 3 parameters"); + exit(1); + } + } + + // }}} + // {{{ doInfo + + function doInfo($command, $options, $params) + { + // $params[0] The package for showing info + if (sizeof($params) != 1) { + return $this->raiseError("This command only accepts one param: ". + "the package you want information"); + } + if (@is_file($params[0])) { + $obj = &new PEAR_Common(); + $info = $obj->infoFromAny($params[0]); + } else { + $reg = &new PEAR_Registry($this->config->get('php_dir')); + $info = $reg->packageInfo($params[0]); + } + if (PEAR::isError($info)) { + return $info; + } + if (empty($info)) { + $this->raiseError("Nothing found for `$params[0]'"); + return; + } + unset($info['filelist']); + unset($info['changelog']); + $keys = array_keys($info); + $longtext = array('description', 'summary'); + foreach ($keys as $key) { + if (is_array($info[$key])) { + switch ($key) { + case 'maintainers': { + $i = 0; + $mstr = ''; + foreach ($info[$key] as $m) { + if ($i++ > 0) { + $mstr .= "\n"; + } + $mstr .= $m['name'] . " <"; + if (isset($m['email'])) { + $mstr .= $m['email']; + } else { + $mstr .= $m['handle'] . '@php.net'; + } + $mstr .= "> ($m[role])"; + } + $info[$key] = $mstr; + break; + } + case 'release_deps': { + $i = 0; + $dstr = ''; + foreach ($info[$key] as $d) { + if (isset($this->_deps_rel_trans[$d['rel']])) { + $rel = $this->_deps_rel_trans[$d['rel']]; + } else { + $rel = $d['rel']; + } + if (isset($this->_deps_type_trans[$d['type']])) { + $type = ucfirst($this->_deps_type_trans[$d['type']]); + } else { + $type = $d['type']; + } + if (isset($d['name'])) { + $name = $d['name'] . ' '; + } else { + $name = ''; + } + if (isset($d['version'])) { + $version = $d['version'] . ' '; + } else { + $version = ''; + } + $dstr .= "$type $name$rel $version\n"; + } + $info[$key] = $dstr; + break; + } + case 'provides' : { + $debug = $this->config->get('verbose'); + if ($debug < 2) { + $pstr = 'Classes: '; + } else { + $pstr = ''; + } + $i = 0; + foreach ($info[$key] as $p) { + if ($debug < 2 && $p['type'] != "class") { + continue; + } + // Only print classes when verbosity mode is < 2 + if ($debug < 2) { + if ($i++ > 0) { + $pstr .= ", "; + } + $pstr .= $p['name']; + } else { + if ($i++ > 0) { + $pstr .= "\n"; + } + $pstr .= ucfirst($p['type']) . " " . $p['name']; + if (isset($p['explicit']) && $p['explicit'] == 1) { + $pstr .= " (explicit)"; + } + } + } + $info[$key] = $pstr; + break; + } + default: { + $info[$key] = implode(", ", $info[$key]); + break; + } + } + } + if ($key == '_lastmodified') { + $hdate = date('Y-m-d', $info[$key]); + unset($info[$key]); + $info['Last Modified'] = $hdate; + } else { + $info[$key] = trim($info[$key]); + if (in_array($key, $longtext)) { + $info[$key] = preg_replace('/ +/', ' ', $info[$key]); + } + } + } + $caption = 'About ' . $info['package'] . '-' . $info['version']; + $data = array( + 'caption' => $caption, + 'border' => true); + foreach ($info as $key => $value) { + $key = ucwords(trim(str_replace('_', ' ', $key))); + $data['data'][] = array($key, $value); + } + $data['raw'] = $info; + + $this->ui->outputData($data, 'package-info'); + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Command/Remote.php b/common/PEAR/PEAR/Command/Remote.php new file mode 100644 index 0000000..325bf07 --- /dev/null +++ b/common/PEAR/PEAR/Command/Remote.php @@ -0,0 +1,435 @@ + | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Remote.php,v 1.22.2.17 2004/04/03 15:56:11 cellog Exp $ + +require_once 'PEAR/Command/Common.php'; +require_once 'PEAR/Common.php'; +require_once 'PEAR/Remote.php'; +require_once 'PEAR/Registry.php'; + +class PEAR_Command_Remote extends PEAR_Command_Common +{ + // {{{ command definitions + + var $commands = array( + 'remote-info' => array( + 'summary' => 'Information About Remote Packages', + 'function' => 'doRemoteInfo', + 'shortcut' => 'ri', + 'options' => array(), + 'doc' => ' +Get details on a package from the server.', + ), + 'list-upgrades' => array( + 'summary' => 'List Available Upgrades', + 'function' => 'doListUpgrades', + 'shortcut' => 'lu', + 'options' => array(), + 'doc' => ' +List releases on the server of packages you have installed where +a newer version is available with the same release state (stable etc.).' + ), + 'remote-list' => array( + 'summary' => 'List Remote Packages', + 'function' => 'doRemoteList', + 'shortcut' => 'rl', + 'options' => array(), + 'doc' => ' +Lists the packages available on the configured server along with the +latest stable release of each package.', + ), + 'search' => array( + 'summary' => 'Search remote package database', + 'function' => 'doSearch', + 'shortcut' => 'sp', + 'options' => array(), + 'doc' => ' +Lists all packages which match the search parameters (first param +is package name, second package info)', + ), + 'list-all' => array( + 'summary' => 'List All Packages', + 'function' => 'doListAll', + 'shortcut' => 'la', + 'options' => array(), + 'doc' => ' +Lists the packages available on the configured server along with the +latest stable release of each package.', + ), + 'download' => array( + 'summary' => 'Download Package', + 'function' => 'doDownload', + 'shortcut' => 'd', + 'options' => array( + 'nocompress' => array( + 'shortopt' => 'Z', + 'doc' => 'download an uncompressed (.tar) file', + ), + ), + 'doc' => '{package|package-version} +Download a package tarball. The file will be named as suggested by the +server, for example if you download the DB package and the latest stable +version of DB is 1.2, the downloaded file will be DB-1.2.tgz.', + ), + 'clear-cache' => array( + 'summary' => 'Clear XML-RPC Cache', + 'function' => 'doClearCache', + 'shortcut' => 'cc', + 'options' => array(), + 'doc' => ' +Clear the XML-RPC cache. See also the cache_ttl configuration +parameter. +', + ), + ); + + // }}} + // {{{ constructor + + /** + * PEAR_Command_Remote constructor. + * + * @access public + */ + function PEAR_Command_Remote(&$ui, &$config) + { + parent::PEAR_Command_Common($ui, $config); + } + + // }}} + + // {{{ doRemoteInfo() + + function doRemoteInfo($command, $options, $params) + { + if (sizeof($params) != 1) { + return $this->raiseError("$command expects one param: the remote package name"); + } + $r = new PEAR_Remote($this->config); + $info = $r->call('package.info', $params[0]); + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + + $reg = new PEAR_Registry($this->config->get('php_dir')); + $installed = $reg->packageInfo($info['name']); + $info['installed'] = $installed['version'] ? $installed['version'] : '- no -'; + + $this->ui->outputData($info, $command); + + return true; + } + + // }}} + // {{{ doRemoteList() + + function doRemoteList($command, $options, $params) + { + $r = new PEAR_Remote($this->config); + $list_options = false; + if ($this->config->get('preferred_state') == 'stable') + $list_options = true; + $available = $r->call('package.listAll', $list_options); + if (PEAR::isError($available)) { + return $this->raiseError($available); + } + $i = $j = 0; + $data = array( + 'caption' => 'Available packages:', + 'border' => true, + 'headline' => array('Package', 'Version'), + ); + foreach ($available as $name => $info) { + $data['data'][] = array($name, isset($info['stable']) ? $info['stable'] : '-n/a-'); + } + if (count($available)==0) { + $data = '(no packages installed yet)'; + } + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doListAll() + + function doListAll($command, $options, $params) + { + $r = new PEAR_Remote($this->config); + $reg = new PEAR_Registry($this->config->get('php_dir')); + $list_options = false; + if ($this->config->get('preferred_state') == 'stable') + $list_options = true; + $available = $r->call('package.listAll', $list_options); + if (PEAR::isError($available)) { + return $this->raiseError($available); + } + if (!is_array($available)) { + return $this->raiseError('The package list could not be fetched from the remote server. Please try again. (Debug info: "'.$available.'")'); + } + $data = array( + 'caption' => 'All packages:', + 'border' => true, + 'headline' => array('Package', 'Latest', 'Local'), + ); + $local_pkgs = $reg->listPackages(); + + foreach ($available as $name => $info) { + $installed = $reg->packageInfo($name); + $desc = $info['summary']; + if (isset($params[$name])) + $desc .= "\n\n".$info['description']; + + if (isset($options['mode'])) + { + if ($options['mode'] == 'installed' && !isset($installed['version'])) + continue; + if ($options['mode'] == 'notinstalled' && isset($installed['version'])) + continue; + if ($options['mode'] == 'upgrades' + && (!isset($installed['version']) || $installed['version'] == $info['stable'])) + { + continue; + } + } + $pos = array_search(strtolower($name), $local_pkgs); + if ($pos !== false) { + unset($local_pkgs[$pos]); + } + + $data['data'][$info['category']][] = array( + $name, + @$info['stable'], + @$installed['version'], + @$desc, + @$info['deps'], + ); + } + + foreach ($local_pkgs as $name) { + $info = $reg->packageInfo($name); + $data['data']['Local'][] = array( + $info['package'], + '', + $info['version'], + $info['summary'], + @$info['release_deps'] + ); + } + + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doSearch() + + function doSearch($command, $options, $params) + { + if ((!isset($params[0]) || empty($params[0])) + && (!isset($params[1]) || empty($params[1]))) + { + return $this->raiseError('no valid search string supplied'); + }; + + $r = new PEAR_Remote($this->config); + $reg = new PEAR_Registry($this->config->get('php_dir')); + $available = $r->call('package.listAll', true, false); + if (PEAR::isError($available)) { + return $this->raiseError($available); + } + $data = array( + 'caption' => 'Matched packages:', + 'border' => true, + 'headline' => array('Package', 'Stable/(Latest)', 'Local'), + ); + + foreach ($available as $name => $info) { + $found = (!empty($params[0]) && stristr($name, $params[0]) !== false); + if (!$found && !(isset($params[1]) && !empty($params[1]) + && (stristr($info['summary'], $params[1]) !== false + || stristr($info['description'], $params[1]) !== false))) + { + continue; + }; + + $installed = $reg->packageInfo($name); + $desc = $info['summary']; + if (isset($params[$name])) + $desc .= "\n\n".$info['description']; + + $unstable = ''; + if ($info['unstable']) { + $unstable = '/(' . $info['unstable'] . $info['state'] . ')'; + } + if (!isset($info['stable']) || !$info['stable']) { + $info['stable'] = 'none'; + } + $data['data'][$info['category']][] = array( + $name, + $info['stable'] . $unstable, + $installed['version'], + $desc, + ); + } + if (!isset($data['data'])) { + return $this->raiseError('no packages found'); + } + $this->ui->outputData($data, $command); + return true; + } + + // }}} + // {{{ doDownload() + + function doDownload($command, $options, $params) + { + //$params[0] -> The package to download + if (count($params) != 1) { + return PEAR::raiseError("download expects one argument: the package to download"); + } + $server = $this->config->get('master_server'); + if (!ereg('^http://', $params[0])) { + $getoption = isset($options['nocompress'])&&$options['nocompress']==1?'?uncompress=on':''; + $pkgfile = "http://$server/get/$params[0]".$getoption; + } else { + $pkgfile = $params[0]; + } + $this->bytes_downloaded = 0; + $saved = PEAR_Common::downloadHttp($pkgfile, $this->ui, '.', + array(&$this, 'downloadCallback')); + if (PEAR::isError($saved)) { + return $this->raiseError($saved); + } + $fname = basename($saved); + $this->ui->outputData("File $fname downloaded ($this->bytes_downloaded bytes)", $command); + return true; + } + + function downloadCallback($msg, $params = null) + { + if ($msg == 'done') { + $this->bytes_downloaded = $params; + } + } + + // }}} + // {{{ doListUpgrades() + + function doListUpgrades($command, $options, $params) + { + include_once "PEAR/Registry.php"; + $remote = new PEAR_Remote($this->config); + if (empty($params[0])) { + $state = $this->config->get('preferred_state'); + } else { + $state = $params[0]; + } + $caption = 'Available Upgrades'; + if (empty($state) || $state == 'any') { + $latest = $remote->call("package.listLatestReleases"); + } else { + $latest = $remote->call("package.listLatestReleases", $state); + $caption .= ' (' . implode(', ', PEAR_Common::betterStates($state, true)) . ')'; + } + $caption .= ':'; + if (PEAR::isError($latest)) { + return $latest; + } + $reg = new PEAR_Registry($this->config->get('php_dir')); + $inst = array_flip($reg->listPackages()); + $data = array( + 'caption' => $caption, + 'border' => 1, + 'headline' => array('Package', 'Local', 'Remote', 'Size'), + ); + foreach ((array)$latest as $pkg => $info) { + $package = strtolower($pkg); + if (!isset($inst[$package])) { + // skip packages we don't have installed + continue; + } + extract($info); + $pkginfo = $reg->packageInfo($package); + $inst_version = $pkginfo['version']; + $inst_state = $pkginfo['release_state']; + if (version_compare("$version", "$inst_version", "le")) { + // installed version is up-to-date + continue; + } + if ($filesize >= 20480) { + $filesize += 1024 - ($filesize % 1024); + $fs = sprintf("%dkB", $filesize / 1024); + } elseif ($filesize > 0) { + $filesize += 103 - ($filesize % 103); + $fs = sprintf("%.1fkB", $filesize / 1024.0); + } else { + $fs = " -"; // XXX center instead + } + $data['data'][] = array($pkg, "$inst_version ($inst_state)", "$version ($state)", $fs); + } + if (empty($data['data'])) { + $this->ui->outputData('No upgrades available'); + } else { + $this->ui->outputData($data, $command); + } + return true; + } + + // }}} + // {{{ doClearCache() + + function doClearCache($command, $options, $params) + { + $cache_dir = $this->config->get('cache_dir'); + $verbose = $this->config->get('verbose'); + $output = ''; + if (!($dp = @opendir($cache_dir))) { + return $this->raiseError("opendir($cache_dir) failed: $php_errormsg"); + } + if ($verbose >= 1) { + $output .= "reading directory $cache_dir\n"; + } + $num = 0; + while ($ent = readdir($dp)) { + if (preg_match('/^xmlrpc_cache_[a-z0-9]{32}$/', $ent)) { + $path = $cache_dir . DIRECTORY_SEPARATOR . $ent; + $ok = @unlink($path); + if ($ok) { + if ($verbose >= 2) { + $output .= "deleted $path\n"; + } + $num++; + } elseif ($verbose >= 1) { + $output .= "failed to delete $path\n"; + } + } + } + closedir($dp); + if ($verbose >= 1) { + $output .= "$num cache entries cleared\n"; + } + $this->ui->outputData(rtrim($output), $command); + return $num; + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Common.php b/common/PEAR/PEAR/Common.php new file mode 100644 index 0000000..40511ff --- /dev/null +++ b/common/PEAR/PEAR/Common.php @@ -0,0 +1,2040 @@ + | +// | Tomas V.V.Cox | +// +----------------------------------------------------------------------+ +// +// $Id: Common.php,v 1.81.2.18 2004/06/12 06:16:17 cellog Exp $ + +require_once 'PEAR.php'; +require_once 'Archive/Tar.php'; +require_once 'System.php'; +require_once 'PEAR/Config.php'; + +// {{{ constants and globals + +/** + * PEAR_Common error when an invalid PHP file is passed to PEAR_Common::analyzeSourceCode() + */ +define('PEAR_COMMON_ERROR_INVALIDPHP', 1); +define('_PEAR_COMMON_PACKAGE_NAME_PREG', '[A-Za-z][a-zA-Z0-9_]+'); +define('PEAR_COMMON_PACKAGE_NAME_PREG', '/^' . _PEAR_COMMON_PACKAGE_NAME_PREG . '$/'); + +// this should allow: 1, 1.0, 1.0RC1, 1.0dev, 1.0dev123234234234, 1.0a1, 1.0b1, 1.0pl1 +define('_PEAR_COMMON_PACKAGE_VERSION_PREG', '\d+(?:\.\d+)*(?:[a-z]+\d*)?'); +define('PEAR_COMMON_PACKAGE_VERSION_PREG', '/^' . _PEAR_COMMON_PACKAGE_VERSION_PREG . '$/i'); + +// XXX far from perfect :-) +define('PEAR_COMMON_PACKAGE_DOWNLOAD_PREG', '/^(' . _PEAR_COMMON_PACKAGE_NAME_PREG . ')(-([.0-9a-zA-Z]+))?$/'); + +/** + * List of temporary files and directories registered by + * PEAR_Common::addTempFile(). + * @var array + */ +$GLOBALS['_PEAR_Common_tempfiles'] = array(); + +/** + * Valid maintainer roles + * @var array + */ +$GLOBALS['_PEAR_Common_maintainer_roles'] = array('lead','developer','contributor','helper'); + +/** + * Valid release states + * @var array + */ +$GLOBALS['_PEAR_Common_release_states'] = array('alpha','beta','stable','snapshot','devel'); + +/** + * Valid dependency types + * @var array + */ +$GLOBALS['_PEAR_Common_dependency_types'] = array('pkg','ext','php','prog','ldlib','rtlib','os','websrv','sapi'); + +/** + * Valid dependency relations + * @var array + */ +$GLOBALS['_PEAR_Common_dependency_relations'] = array('has','eq','lt','le','gt','ge','not'); + +/** + * Valid file roles + * @var array + */ +$GLOBALS['_PEAR_Common_file_roles'] = array('php','ext','test','doc','data','src','script'); + +/** + * Valid replacement types + * @var array + */ +$GLOBALS['_PEAR_Common_replacement_types'] = array('php-const', 'pear-config', 'package-info'); + +/** + * Valid "provide" types + * @var array + */ +$GLOBALS['_PEAR_Common_provide_types'] = array('ext', 'prog', 'class', 'function', 'feature', 'api'); + +/** + * Valid "provide" types + * @var array + */ +$GLOBALS['_PEAR_Common_script_phases'] = array('pre-install', 'post-install', 'pre-uninstall', 'post-uninstall', 'pre-build', 'post-build', 'pre-configure', 'post-configure', 'pre-setup', 'post-setup'); + +// }}} + +/** + * Class providing common functionality for PEAR adminsitration classes. + */ +class PEAR_Common extends PEAR +{ + // {{{ properties + + /** stack of elements, gives some sort of XML context */ + var $element_stack = array(); + + /** name of currently parsed XML element */ + var $current_element; + + /** array of attributes of the currently parsed XML element */ + var $current_attributes = array(); + + /** assoc with information about a package */ + var $pkginfo = array(); + + /** + * User Interface object (PEAR_Frontend_* class). If null, + * the log() method uses print. + * @var object + */ + var $ui = null; + + /** + * Configuration object (PEAR_Config). + * @var object + */ + var $config = null; + + var $current_path = null; + + /** + * PEAR_SourceAnalyzer instance + * @var object + */ + var $source_analyzer = null; + /** + * Flag variable used to mark a valid package file + * @var boolean + * @access private + */ + var $_validPackageFile; + /** + * Temporary variable used in sorting packages by dependency in {@link sortPkgDeps()} + * @var array + * @access private + */ + var $_packageSortTree; + + // }}} + + // {{{ constructor + + /** + * PEAR_Common constructor + * + * @access public + */ + function PEAR_Common() + { + parent::PEAR(); + $this->config = &PEAR_Config::singleton(); + $this->debug = $this->config->get('verbose'); + } + + // }}} + // {{{ destructor + + /** + * PEAR_Common destructor + * + * @access private + */ + function _PEAR_Common() + { + // doesn't work due to bug #14744 + //$tempfiles = $this->_tempfiles; + $tempfiles =& $GLOBALS['_PEAR_Common_tempfiles']; + while ($file = array_shift($tempfiles)) { + if (@is_dir($file)) { + System::rm(array('-rf', $file)); + } elseif (file_exists($file)) { + unlink($file); + } + } + } + + // }}} + // {{{ addTempFile() + + /** + * Register a temporary file or directory. When the destructor is + * executed, all registered temporary files and directories are + * removed. + * + * @param string $file name of file or directory + * + * @return void + * + * @access public + */ + function addTempFile($file) + { + $GLOBALS['_PEAR_Common_tempfiles'][] = $file; + } + + // }}} + // {{{ mkDirHier() + + /** + * Wrapper to System::mkDir(), creates a directory as well as + * any necessary parent directories. + * + * @param string $dir directory name + * + * @return bool TRUE on success, or a PEAR error + * + * @access public + */ + function mkDirHier($dir) + { + $this->log(2, "+ create dir $dir"); + return System::mkDir(array('-p', $dir)); + } + + // }}} + // {{{ log() + + /** + * Logging method. + * + * @param int $level log level (0 is quiet, higher is noisier) + * @param string $msg message to write to the log + * + * @return void + * + * @access public + */ + function log($level, $msg, $append_crlf = true) + { + if ($this->debug >= $level) { + if (is_object($this->ui)) { + $this->ui->log($msg, $append_crlf); + } else { + print "$msg\n"; + } + } + } + + // }}} + // {{{ mkTempDir() + + /** + * Create and register a temporary directory. + * + * @param string $tmpdir (optional) Directory to use as tmpdir. + * Will use system defaults (for example + * /tmp or c:\windows\temp) if not specified + * + * @return string name of created directory + * + * @access public + */ + function mkTempDir($tmpdir = '') + { + if ($tmpdir) { + $topt = array('-t', $tmpdir); + } else { + $topt = array(); + } + $topt = array_merge($topt, array('-d', 'pear')); + if (!$tmpdir = System::mktemp($topt)) { + return false; + } + $this->addTempFile($tmpdir); + return $tmpdir; + } + + // }}} + // {{{ setFrontendObject() + + /** + * Set object that represents the frontend to be used. + * + * @param object Reference of the frontend object + * @return void + * @access public + */ + function setFrontendObject(&$ui) + { + $this->ui = &$ui; + } + + // }}} + + // {{{ _unIndent() + + /** + * Unindent given string (?) + * + * @param string $str The string that has to be unindented. + * @return string + * @access private + */ + function _unIndent($str) + { + // remove leading newlines + $str = preg_replace('/^[\r\n]+/', '', $str); + // find whitespace at the beginning of the first line + $indent_len = strspn($str, " \t"); + $indent = substr($str, 0, $indent_len); + $data = ''; + // remove the same amount of whitespace from following lines + foreach (explode("\n", $str) as $line) { + if (substr($line, 0, $indent_len) == $indent) { + $data .= substr($line, $indent_len) . "\n"; + } + } + return $data; + } + + // }}} + // {{{ _element_start() + + /** + * XML parser callback for starting elements. Used while package + * format version is not yet known. + * + * @param resource $xp XML parser resource + * @param string $name name of starting element + * @param array $attribs element attributes, name => value + * + * @return void + * + * @access private + */ + function _element_start($xp, $name, $attribs) + { + array_push($this->element_stack, $name); + $this->current_element = $name; + $spos = sizeof($this->element_stack) - 2; + $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : ''; + $this->current_attributes = $attribs; + switch ($name) { + case 'package': { + $this->_validPackageFile = true; + if (isset($attribs['version'])) { + $vs = preg_replace('/[^0-9a-z]/', '_', $attribs['version']); + } else { + $vs = '1_0'; + } + $elem_start = '_element_start_'. $vs; + $elem_end = '_element_end_'. $vs; + $cdata = '_pkginfo_cdata_'. $vs; + if (!method_exists($this, $elem_start) || + !method_exists($this, $elem_end) || + !method_exists($this, $cdata)) { + $this->raiseError("No handlers for package.xml version $attribs[version]"); + return; + } + xml_set_element_handler($xp, $elem_start, $elem_end); + xml_set_character_data_handler($xp, $cdata); + break; + } + } + } + + // }}} + // {{{ _element_end() + + /** + * XML parser callback for ending elements. Used while package + * format version is not yet known. + * + * @param resource $xp XML parser resource + * @param string $name name of ending element + * + * @return void + * + * @access private + */ + function _element_end($xp, $name) + { + } + + // }}} + + // Support for package DTD v1.0: + // {{{ _element_start_1_0() + + /** + * XML parser callback for ending elements. Used for version 1.0 + * packages. + * + * @param resource $xp XML parser resource + * @param string $name name of ending element + * + * @return void + * + * @access private + */ + function _element_start_1_0($xp, $name, $attribs) + { + array_push($this->element_stack, $name); + $this->current_element = $name; + $spos = sizeof($this->element_stack) - 2; + $this->prev_element = ($spos >= 0) ? $this->element_stack[$spos] : ''; + $this->current_attributes = $attribs; + $this->cdata = ''; + switch ($name) { + case 'dir': + if ($this->in_changelog) { + break; + } + if ($attribs['name'] != '/') { + $this->dir_names[] = $attribs['name']; + } + if (isset($attribs['baseinstalldir'])) { + $this->dir_install = $attribs['baseinstalldir']; + } + if (isset($attribs['role'])) { + $this->dir_role = $attribs['role']; + } + break; + case 'file': + if ($this->in_changelog) { + break; + } + if (isset($attribs['name'])) { + $path = ''; + if (count($this->dir_names)) { + foreach ($this->dir_names as $dir) { + $path .= $dir . DIRECTORY_SEPARATOR; + } + } + $path .= $attribs['name']; + unset($attribs['name']); + $this->current_path = $path; + $this->filelist[$path] = $attribs; + // Set the baseinstalldir only if the file don't have this attrib + if (!isset($this->filelist[$path]['baseinstalldir']) && + isset($this->dir_install)) + { + $this->filelist[$path]['baseinstalldir'] = $this->dir_install; + } + // Set the Role + if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) { + $this->filelist[$path]['role'] = $this->dir_role; + } + } + break; + case 'replace': + if (!$this->in_changelog) { + $this->filelist[$this->current_path]['replacements'][] = $attribs; + } + break; + case 'maintainers': + $this->pkginfo['maintainers'] = array(); + $this->m_i = 0; // maintainers array index + break; + case 'maintainer': + // compatibility check + if (!isset($this->pkginfo['maintainers'])) { + $this->pkginfo['maintainers'] = array(); + $this->m_i = 0; + } + $this->pkginfo['maintainers'][$this->m_i] = array(); + $this->current_maintainer =& $this->pkginfo['maintainers'][$this->m_i]; + break; + case 'changelog': + $this->pkginfo['changelog'] = array(); + $this->c_i = 0; // changelog array index + $this->in_changelog = true; + break; + case 'release': + if ($this->in_changelog) { + $this->pkginfo['changelog'][$this->c_i] = array(); + $this->current_release = &$this->pkginfo['changelog'][$this->c_i]; + } else { + $this->current_release = &$this->pkginfo; + } + break; + case 'deps': + if (!$this->in_changelog) { + $this->pkginfo['release_deps'] = array(); + } + break; + case 'dep': + // dependencies array index + if (!$this->in_changelog) { + $this->d_i++; + $this->pkginfo['release_deps'][$this->d_i] = $attribs; + } + break; + case 'configureoptions': + if (!$this->in_changelog) { + $this->pkginfo['configure_options'] = array(); + } + break; + case 'configureoption': + if (!$this->in_changelog) { + $this->pkginfo['configure_options'][] = $attribs; + } + break; + case 'provides': + if (empty($attribs['type']) || empty($attribs['name'])) { + break; + } + $attribs['explicit'] = true; + $this->pkginfo['provides']["$attribs[type];$attribs[name]"] = $attribs; + break; + } + } + + // }}} + // {{{ _element_end_1_0() + + /** + * XML parser callback for ending elements. Used for version 1.0 + * packages. + * + * @param resource $xp XML parser resource + * @param string $name name of ending element + * + * @return void + * + * @access private + */ + function _element_end_1_0($xp, $name) + { + $data = trim($this->cdata); + switch ($name) { + case 'name': + switch ($this->prev_element) { + case 'package': + // XXX should we check the package name here? + $this->pkginfo['package'] = ereg_replace('[^a-zA-Z0-9._]', '_', $data); + break; + case 'maintainer': + $this->current_maintainer['name'] = $data; + break; + } + break; + case 'summary': + $this->pkginfo['summary'] = $data; + break; + case 'description': + $data = $this->_unIndent($this->cdata); + $this->pkginfo['description'] = $data; + break; + case 'user': + $this->current_maintainer['handle'] = $data; + break; + case 'email': + $this->current_maintainer['email'] = $data; + break; + case 'role': + $this->current_maintainer['role'] = $data; + break; + case 'version': + $data = ereg_replace ('[^a-zA-Z0-9._\-]', '_', $data); + if ($this->in_changelog) { + $this->current_release['version'] = $data; + } else { + $this->pkginfo['version'] = $data; + } + break; + case 'date': + if ($this->in_changelog) { + $this->current_release['release_date'] = $data; + } else { + $this->pkginfo['release_date'] = $data; + } + break; + case 'notes': + // try to "de-indent" release notes in case someone + // has been over-indenting their xml ;-) + $data = $this->_unIndent($this->cdata); + if ($this->in_changelog) { + $this->current_release['release_notes'] = $data; + } else { + $this->pkginfo['release_notes'] = $data; + } + break; + case 'warnings': + if ($this->in_changelog) { + $this->current_release['release_warnings'] = $data; + } else { + $this->pkginfo['release_warnings'] = $data; + } + break; + case 'state': + if ($this->in_changelog) { + $this->current_release['release_state'] = $data; + } else { + $this->pkginfo['release_state'] = $data; + } + break; + case 'license': + if ($this->in_changelog) { + $this->current_release['release_license'] = $data; + } else { + $this->pkginfo['release_license'] = $data; + } + break; + case 'dep': + if ($data && !$this->in_changelog) { + $this->pkginfo['release_deps'][$this->d_i]['name'] = $data; + } + break; + case 'dir': + if ($this->in_changelog) { + break; + } + array_pop($this->dir_names); + break; + case 'file': + if ($this->in_changelog) { + break; + } + if ($data) { + $path = ''; + if (count($this->dir_names)) { + foreach ($this->dir_names as $dir) { + $path .= $dir . DIRECTORY_SEPARATOR; + } + } + $path .= $data; + $this->filelist[$path] = $this->current_attributes; + // Set the baseinstalldir only if the file don't have this attrib + if (!isset($this->filelist[$path]['baseinstalldir']) && + isset($this->dir_install)) + { + $this->filelist[$path]['baseinstalldir'] = $this->dir_install; + } + // Set the Role + if (!isset($this->filelist[$path]['role']) && isset($this->dir_role)) { + $this->filelist[$path]['role'] = $this->dir_role; + } + } + break; + case 'maintainer': + if (empty($this->pkginfo['maintainers'][$this->m_i]['role'])) { + $this->pkginfo['maintainers'][$this->m_i]['role'] = 'lead'; + } + $this->m_i++; + break; + case 'release': + if ($this->in_changelog) { + $this->c_i++; + } + break; + case 'changelog': + $this->in_changelog = false; + break; + } + array_pop($this->element_stack); + $spos = sizeof($this->element_stack) - 1; + $this->current_element = ($spos > 0) ? $this->element_stack[$spos] : ''; + $this->cdata = ''; + } + + // }}} + // {{{ _pkginfo_cdata_1_0() + + /** + * XML parser callback for character data. Used for version 1.0 + * packages. + * + * @param resource $xp XML parser resource + * @param string $name character data + * + * @return void + * + * @access private + */ + function _pkginfo_cdata_1_0($xp, $data) + { + if (isset($this->cdata)) { + $this->cdata .= $data; + } + } + + // }}} + + // {{{ infoFromTgzFile() + + /** + * Returns information about a package file. Expects the name of + * a gzipped tar file as input. + * + * @param string $file name of .tgz file + * + * @return array array with package information + * + * @access public + * + */ + function infoFromTgzFile($file) + { + if (!@is_file($file)) { + return $this->raiseError("could not open file \"$file\""); + } + $tar = new Archive_Tar($file); + if ($this->debug <= 1) { + $tar->pushErrorHandling(PEAR_ERROR_RETURN); + } + $content = $tar->listContent(); + if ($this->debug <= 1) { + $tar->popErrorHandling(); + } + if (!is_array($content)) { + $file = realpath($file); + return $this->raiseError("Could not get contents of package \"$file\"". + '. Invalid tgz file.'); + } + $xml = null; + foreach ($content as $file) { + $name = $file['filename']; + if ($name == 'package.xml') { + $xml = $name; + break; + } elseif (ereg('package.xml$', $name, $match)) { + $xml = $match[0]; + break; + } + } + $tmpdir = System::mkTemp(array('-d', 'pear')); + $this->addTempFile($tmpdir); + if (!$xml || !$tar->extractList(array($xml), $tmpdir)) { + return $this->raiseError('could not extract the package.xml file'); + } + return $this->infoFromDescriptionFile("$tmpdir/$xml"); + } + + // }}} + // {{{ infoFromDescriptionFile() + + /** + * Returns information about a package file. Expects the name of + * a package xml file as input. + * + * @param string $descfile name of package xml file + * + * @return array array with package information + * + * @access public + * + */ + function infoFromDescriptionFile($descfile) + { + if (!@is_file($descfile) || !is_readable($descfile) || + (!$fp = @fopen($descfile, 'r'))) { + return $this->raiseError("Unable to open $descfile"); + } + + // read the whole thing so we only get one cdata callback + // for each block of cdata + $data = fread($fp, filesize($descfile)); + return $this->infoFromString($data); + } + + // }}} + // {{{ infoFromString() + + /** + * Returns information about a package file. Expects the contents + * of a package xml file as input. + * + * @param string $data name of package xml file + * + * @return array array with package information + * + * @access public + * + */ + function infoFromString($data) + { + require_once('PEAR/Dependency.php'); + if (PEAR_Dependency::checkExtension($error, 'xml')) { + return $this->raiseError($error); + } + $xp = @xml_parser_create(); + if (!$xp) { + return $this->raiseError('Unable to create XML parser'); + } + xml_set_object($xp, $this); + xml_set_element_handler($xp, '_element_start', '_element_end'); + xml_set_character_data_handler($xp, '_pkginfo_cdata'); + xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, false); + + $this->element_stack = array(); + $this->pkginfo = array('provides' => array()); + $this->current_element = false; + unset($this->dir_install); + $this->pkginfo['filelist'] = array(); + $this->filelist =& $this->pkginfo['filelist']; + $this->dir_names = array(); + $this->in_changelog = false; + $this->d_i = 0; + $this->cdata = ''; + $this->_validPackageFile = false; + + if (!xml_parse($xp, $data, 1)) { + $code = xml_get_error_code($xp); + $msg = sprintf("XML error: %s at line %d", + xml_error_string($code), + xml_get_current_line_number($xp)); + xml_parser_free($xp); + return $this->raiseError($msg, $code); + } + + xml_parser_free($xp); + + if (!$this->_validPackageFile) { + return $this->raiseError('Invalid Package File, no tag'); + } + foreach ($this->pkginfo as $k => $v) { + if (!is_array($v)) { + $this->pkginfo[$k] = trim($v); + } + } + return $this->pkginfo; + } + // }}} + // {{{ infoFromAny() + + /** + * Returns package information from different sources + * + * This method is able to extract information about a package + * from a .tgz archive or from a XML package definition file. + * + * @access public + * @param string Filename of the source ('package.xml', '.tgz') + * @return string + */ + function infoFromAny($info) + { + if (is_string($info) && file_exists($info)) { + $tmp = substr($info, -4); + if ($tmp == '.xml') { + $info = $this->infoFromDescriptionFile($info); + } elseif ($tmp == '.tar' || $tmp == '.tgz') { + $info = $this->infoFromTgzFile($info); + } else { + $fp = fopen($info, "r"); + $test = fread($fp, 5); + fclose($fp); + if ($test == "infoFromDescriptionFile($info); + } else { + $info = $this->infoFromTgzFile($info); + } + } + if (PEAR::isError($info)) { + return $this->raiseError($info); + } + } + return $info; + } + + // }}} + // {{{ xmlFromInfo() + + /** + * Return an XML document based on the package info (as returned + * by the PEAR_Common::infoFrom* methods). + * + * @param array $pkginfo package info + * + * @return string XML data + * + * @access public + */ + function xmlFromInfo($pkginfo) + { + static $maint_map = array( + "handle" => "user", + "name" => "name", + "email" => "email", + "role" => "role", + ); + $ret = "\n"; + $ret .= "\n"; + $ret .= " + $pkginfo[package] + ".htmlspecialchars($pkginfo['summary'])." + ".htmlspecialchars($pkginfo['description'])." + +"; + foreach ($pkginfo['maintainers'] as $maint) { + $ret .= " \n"; + foreach ($maint_map as $idx => $elm) { + $ret .= " <$elm>"; + $ret .= htmlspecialchars($maint[$idx]); + $ret .= "\n"; + } + $ret .= " \n"; + } + $ret .= " \n"; + $ret .= $this->_makeReleaseXml($pkginfo); + if (@sizeof($pkginfo['changelog']) > 0) { + $ret .= " \n"; + foreach ($pkginfo['changelog'] as $oldrelease) { + $ret .= $this->_makeReleaseXml($oldrelease, true); + } + $ret .= " \n"; + } + $ret .= "\n"; + return $ret; + } + + // }}} + // {{{ _makeReleaseXml() + + /** + * Generate part of an XML description with release information. + * + * @param array $pkginfo array with release information + * @param bool $changelog whether the result will be in a changelog element + * + * @return string XML data + * + * @access private + */ + function _makeReleaseXml($pkginfo, $changelog = false) + { + // XXX QUOTE ENTITIES IN PCDATA, OR EMBED IN CDATA BLOCKS!! + $indent = $changelog ? " " : ""; + $ret = "$indent \n"; + if (!empty($pkginfo['version'])) { + $ret .= "$indent $pkginfo[version]\n"; + } + if (!empty($pkginfo['release_date'])) { + $ret .= "$indent $pkginfo[release_date]\n"; + } + if (!empty($pkginfo['release_license'])) { + $ret .= "$indent $pkginfo[release_license]\n"; + } + if (!empty($pkginfo['release_state'])) { + $ret .= "$indent $pkginfo[release_state]\n"; + } + if (!empty($pkginfo['release_notes'])) { + $ret .= "$indent ".htmlspecialchars($pkginfo['release_notes'])."\n"; + } + if (!empty($pkginfo['release_warnings'])) { + $ret .= "$indent ".htmlspecialchars($pkginfo['release_warnings'])."\n"; + } + if (isset($pkginfo['release_deps']) && sizeof($pkginfo['release_deps']) > 0) { + $ret .= "$indent \n"; + foreach ($pkginfo['release_deps'] as $dep) { + $ret .= "$indent $what) { + $ret .= "$indent $fa) { + @$ret .= "$indent $v) { + $ret .= " $k=\"" . htmlspecialchars($v) .'"'; + } + $ret .= "/>\n"; + } + @$ret .= "$indent \n"; + } + } + $ret .= "$indent \n"; + } + $ret .= "$indent \n"; + return $ret; + } + + // }}} + // {{{ validatePackageInfo() + + /** + * Validate XML package definition file. + * + * @param string $info Filename of the package archive or of the + * package definition file + * @param array $errors Array that will contain the errors + * @param array $warnings Array that will contain the warnings + * @param string $dir_prefix (optional) directory where source files + * may be found, or empty if they are not available + * @access public + * @return boolean + */ + function validatePackageInfo($info, &$errors, &$warnings, $dir_prefix = '') + { + if (PEAR::isError($info = $this->infoFromAny($info))) { + return $this->raiseError($info); + } + if (!is_array($info)) { + return false; + } + + $errors = array(); + $warnings = array(); + if (!isset($info['package'])) { + $errors[] = 'missing package name'; + } elseif (!$this->validPackageName($info['package'])) { + $errors[] = 'invalid package name'; + } + $this->_packageName = $pn = $info['package']; + + if (empty($info['summary'])) { + $errors[] = 'missing summary'; + } elseif (strpos(trim($info['summary']), "\n") !== false) { + $warnings[] = 'summary should be on a single line'; + } + if (empty($info['description'])) { + $errors[] = 'missing description'; + } + if (empty($info['release_license'])) { + $errors[] = 'missing license'; + } + if (!isset($info['version'])) { + $errors[] = 'missing version'; + } elseif (!$this->validPackageVersion($info['version'])) { + $errors[] = 'invalid package release version'; + } + if (empty($info['release_state'])) { + $errors[] = 'missing release state'; + } elseif (!in_array($info['release_state'], PEAR_Common::getReleaseStates())) { + $errors[] = "invalid release state `$info[release_state]', should be one of: " + . implode(' ', PEAR_Common::getReleaseStates()); + } + if (empty($info['release_date'])) { + $errors[] = 'missing release date'; + } elseif (!preg_match('/^\d{4}-\d\d-\d\d$/', $info['release_date'])) { + $errors[] = "invalid release date `$info[release_date]', format is YYYY-MM-DD"; + } + if (empty($info['release_notes'])) { + $errors[] = "missing release notes"; + } + if (empty($info['maintainers'])) { + $errors[] = 'no maintainer(s)'; + } else { + $i = 1; + foreach ($info['maintainers'] as $m) { + if (empty($m['handle'])) { + $errors[] = "maintainer $i: missing handle"; + } + if (empty($m['role'])) { + $errors[] = "maintainer $i: missing role"; + } elseif (!in_array($m['role'], PEAR_Common::getUserRoles())) { + $errors[] = "maintainer $i: invalid role `$m[role]', should be one of: " + . implode(' ', PEAR_Common::getUserRoles()); + } + if (empty($m['name'])) { + $errors[] = "maintainer $i: missing name"; + } + if (empty($m['email'])) { + $errors[] = "maintainer $i: missing email"; + } + $i++; + } + } + if (!empty($info['release_deps'])) { + $i = 1; + foreach ($info['release_deps'] as $d) { + if (empty($d['type'])) { + $errors[] = "dependency $i: missing type"; + } elseif (!in_array($d['type'], PEAR_Common::getDependencyTypes())) { + $errors[] = "dependency $i: invalid type '$d[type]', should be one of: " . + implode(' ', PEAR_Common::getDependencyTypes()); + } + if (empty($d['rel'])) { + $errors[] = "dependency $i: missing relation"; + } elseif (!in_array($d['rel'], PEAR_Common::getDependencyRelations())) { + $errors[] = "dependency $i: invalid relation '$d[rel]', should be one of: " + . implode(' ', PEAR_Common::getDependencyRelations()); + } + if (!empty($d['optional'])) { + if (!in_array($d['optional'], array('yes', 'no'))) { + $errors[] = "dependency $i: invalid relation optional attribute '$d[optional]', should be one of: yes no"; + } + } + if ($d['rel'] != 'has' && empty($d['version'])) { + $warnings[] = "dependency $i: missing version"; + } elseif ($d['rel'] == 'has' && !empty($d['version'])) { + $warnings[] = "dependency $i: version ignored for `has' dependencies"; + } + if ($d['type'] == 'php' && !empty($d['name'])) { + $warnings[] = "dependency $i: name ignored for php type dependencies"; + } elseif ($d['type'] != 'php' && empty($d['name'])) { + $errors[] = "dependency $i: missing name"; + } + $i++; + } + } + if (!empty($info['configure_options'])) { + $i = 1; + foreach ($info['configure_options'] as $c) { + if (empty($c['name'])) { + $errors[] = "configure option $i: missing name"; + } + if (empty($c['prompt'])) { + $errors[] = "configure option $i: missing prompt"; + } + $i++; + } + } + if (empty($info['filelist'])) { + $errors[] = 'no files'; + } else { + foreach ($info['filelist'] as $file => $fa) { + if (empty($fa['role'])) { + $errors[] = "file $file: missing role"; + continue; + } elseif (!in_array($fa['role'], PEAR_Common::getFileRoles())) { + $errors[] = "file $file: invalid role, should be one of: " + . implode(' ', PEAR_Common::getFileRoles()); + } + if ($fa['role'] == 'php' && $dir_prefix) { + $this->log(1, "Analyzing $file"); + $srcinfo = $this->analyzeSourceCode($dir_prefix . DIRECTORY_SEPARATOR . $file); + if ($srcinfo) { + $this->buildProvidesArray($srcinfo); + } + } + + // (ssb) Any checks we can do for baseinstalldir? + // (cox) Perhaps checks that either the target dir and + // baseInstall doesn't cointain "../../" + } + } + $this->_packageName = $pn = $info['package']; + $pnl = strlen($pn); + foreach ((array)$this->pkginfo['provides'] as $key => $what) { + if (isset($what['explicit'])) { + // skip conformance checks if the provides entry is + // specified in the package.xml file + continue; + } + extract($what); + if ($type == 'class') { + if (!strncasecmp($name, $pn, $pnl)) { + continue; + } + $warnings[] = "in $file: class \"$name\" not prefixed with package name \"$pn\""; + } elseif ($type == 'function') { + if (strstr($name, '::') || !strncasecmp($name, $pn, $pnl)) { + continue; + } + $warnings[] = "in $file: function \"$name\" not prefixed with package name \"$pn\""; + } + } + + + return true; + } + + // }}} + // {{{ buildProvidesArray() + + /** + * Build a "provides" array from data returned by + * analyzeSourceCode(). The format of the built array is like + * this: + * + * array( + * 'class;MyClass' => 'array('type' => 'class', 'name' => 'MyClass'), + * ... + * ) + * + * + * @param array $srcinfo array with information about a source file + * as returned by the analyzeSourceCode() method. + * + * @return void + * + * @access public + * + */ + function buildProvidesArray($srcinfo) + { + $file = basename($srcinfo['source_file']); + $pn = ''; + if (isset($this->_packageName)) { + $pn = $this->_packageName; + } + $pnl = strlen($pn); + foreach ($srcinfo['declared_classes'] as $class) { + $key = "class;$class"; + if (isset($this->pkginfo['provides'][$key])) { + continue; + } + $this->pkginfo['provides'][$key] = + array('file'=> $file, 'type' => 'class', 'name' => $class); + if (isset($srcinfo['inheritance'][$class])) { + $this->pkginfo['provides'][$key]['extends'] = + $srcinfo['inheritance'][$class]; + } + } + foreach ($srcinfo['declared_methods'] as $class => $methods) { + foreach ($methods as $method) { + $function = "$class::$method"; + $key = "function;$function"; + if ($method{0} == '_' || !strcasecmp($method, $class) || + isset($this->pkginfo['provides'][$key])) { + continue; + } + $this->pkginfo['provides'][$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + } + + foreach ($srcinfo['declared_functions'] as $function) { + $key = "function;$function"; + if ($function{0} == '_' || isset($this->pkginfo['provides'][$key])) { + continue; + } + if (!strstr($function, '::') && strncasecmp($function, $pn, $pnl)) { + $warnings[] = "in1 " . $file . ": function \"$function\" not prefixed with package name \"$pn\""; + } + $this->pkginfo['provides'][$key] = + array('file'=> $file, 'type' => 'function', 'name' => $function); + } + } + + // }}} + // {{{ analyzeSourceCode() + + /** + * Analyze the source code of the given PHP file + * + * @param string Filename of the PHP file + * @return mixed + * @access public + */ + function analyzeSourceCode($file) + { + if (!function_exists("token_get_all")) { + return false; + } + if (!$fp = @fopen($file, "r")) { + return false; + } + $contents = fread($fp, filesize($file)); + $tokens = token_get_all($contents); +/* + for ($i = 0; $i < sizeof($tokens); $i++) { + @list($token, $data) = $tokens[$i]; + if (is_string($token)) { + var_dump($token); + } else { + print token_name($token) . ' '; + var_dump(rtrim($data)); + } + } +*/ + $look_for = 0; + $paren_level = 0; + $bracket_level = 0; + $brace_level = 0; + $lastphpdoc = ''; + $current_class = ''; + $current_class_level = -1; + $current_function = ''; + $current_function_level = -1; + $declared_classes = array(); + $declared_functions = array(); + $declared_methods = array(); + $used_classes = array(); + $used_functions = array(); + $extends = array(); + $nodeps = array(); + $inquote = false; + for ($i = 0; $i < sizeof($tokens); $i++) { + if (is_array($tokens[$i])) { + list($token, $data) = $tokens[$i]; + } else { + $token = $tokens[$i]; + $data = ''; + } + if ($inquote) { + if ($token != '"') { + continue; + } else { + $inquote = false; + } + } + switch ($token) { + case '"': + $inquote = true; + break; + case T_CURLY_OPEN: + case T_DOLLAR_OPEN_CURLY_BRACES: + case '{': $brace_level++; continue 2; + case '}': + $brace_level--; + if ($current_class_level == $brace_level) { + $current_class = ''; + $current_class_level = -1; + } + if ($current_function_level == $brace_level) { + $current_function = ''; + $current_function_level = -1; + } + continue 2; + case '[': $bracket_level++; continue 2; + case ']': $bracket_level--; continue 2; + case '(': $paren_level++; continue 2; + case ')': $paren_level--; continue 2; + case T_CLASS: + if (($current_class_level != -1) || ($current_function_level != -1)) { + PEAR::raiseError("Parser error: Invalid PHP file $file", + PEAR_COMMON_ERROR_INVALIDPHP); + return false; + } + case T_FUNCTION: + case T_NEW: + case T_EXTENDS: + $look_for = $token; + continue 2; + case T_STRING: + if ($look_for == T_CLASS) { + $current_class = $data; + $current_class_level = $brace_level; + $declared_classes[] = $current_class; + } elseif ($look_for == T_EXTENDS) { + $extends[$current_class] = $data; + } elseif ($look_for == T_FUNCTION) { + if ($current_class) { + $current_function = "$current_class::$data"; + $declared_methods[$current_class][] = $data; + } else { + $current_function = $data; + $declared_functions[] = $current_function; + } + $current_function_level = $brace_level; + $m = array(); + } elseif ($look_for == T_NEW) { + $used_classes[$data] = true; + } + $look_for = 0; + continue 2; + case T_VARIABLE: + $look_for = 0; + continue 2; + case T_COMMENT: + if (preg_match('!^/\*\*\s!', $data)) { + $lastphpdoc = $data; + if (preg_match_all('/@nodep\s+(\S+)/', $lastphpdoc, $m)) { + $nodeps = array_merge($nodeps, $m[1]); + } + } + continue 2; + case T_DOUBLE_COLON: + if (!($tokens[$i - 1][0] == T_WHITESPACE || $tokens[$i - 1][0] == T_STRING)) { + PEAR::raiseError("Parser error: Invalid PHP file $file", + PEAR_COMMON_ERROR_INVALIDPHP); + return false; + } + $class = $tokens[$i - 1][1]; + if (strtolower($class) != 'parent') { + $used_classes[$class] = true; + } + continue 2; + } + } + return array( + "source_file" => $file, + "declared_classes" => $declared_classes, + "declared_methods" => $declared_methods, + "declared_functions" => $declared_functions, + "used_classes" => array_diff(array_keys($used_classes), $nodeps), + "inheritance" => $extends, + ); + } + + // }}} + // {{{ betterStates() + + /** + * Return an array containing all of the states that are more stable than + * or equal to the passed in state + * + * @param string Release state + * @param boolean Determines whether to include $state in the list + * @return false|array False if $state is not a valid release state + */ + function betterStates($state, $include = false) + { + static $states = array('snapshot', 'devel', 'alpha', 'beta', 'stable'); + $i = array_search($state, $states); + if ($i === false) { + return false; + } + if ($include) { + $i--; + } + return array_slice($states, $i + 1); + } + + // }}} + // {{{ detectDependencies() + + function detectDependencies($any, $status_callback = null) + { + if (!function_exists("token_get_all")) { + return false; + } + if (PEAR::isError($info = $this->infoFromAny($any))) { + return $this->raiseError($info); + } + if (!is_array($info)) { + return false; + } + $deps = array(); + $used_c = $decl_c = $decl_f = $decl_m = array(); + foreach ($info['filelist'] as $file => $fa) { + $tmp = $this->analyzeSourceCode($file); + $used_c = @array_merge($used_c, $tmp['used_classes']); + $decl_c = @array_merge($decl_c, $tmp['declared_classes']); + $decl_f = @array_merge($decl_f, $tmp['declared_functions']); + $decl_m = @array_merge($decl_m, $tmp['declared_methods']); + $inheri = @array_merge($inheri, $tmp['inheritance']); + } + $used_c = array_unique($used_c); + $decl_c = array_unique($decl_c); + $undecl_c = array_diff($used_c, $decl_c); + return array('used_classes' => $used_c, + 'declared_classes' => $decl_c, + 'declared_methods' => $decl_m, + 'declared_functions' => $decl_f, + 'undeclared_classes' => $undecl_c, + 'inheritance' => $inheri, + ); + } + + // }}} + // {{{ getUserRoles() + + /** + * Get the valid roles for a PEAR package maintainer + * + * @return array + * @static + */ + function getUserRoles() + { + return $GLOBALS['_PEAR_Common_maintainer_roles']; + } + + // }}} + // {{{ getReleaseStates() + + /** + * Get the valid package release states of packages + * + * @return array + * @static + */ + function getReleaseStates() + { + return $GLOBALS['_PEAR_Common_release_states']; + } + + // }}} + // {{{ getDependencyTypes() + + /** + * Get the implemented dependency types (php, ext, pkg etc.) + * + * @return array + * @static + */ + function getDependencyTypes() + { + return $GLOBALS['_PEAR_Common_dependency_types']; + } + + // }}} + // {{{ getDependencyRelations() + + /** + * Get the implemented dependency relations (has, lt, ge etc.) + * + * @return array + * @static + */ + function getDependencyRelations() + { + return $GLOBALS['_PEAR_Common_dependency_relations']; + } + + // }}} + // {{{ getFileRoles() + + /** + * Get the implemented file roles + * + * @return array + * @static + */ + function getFileRoles() + { + return $GLOBALS['_PEAR_Common_file_roles']; + } + + // }}} + // {{{ getReplacementTypes() + + /** + * Get the implemented file replacement types in + * + * @return array + * @static + */ + function getReplacementTypes() + { + return $GLOBALS['_PEAR_Common_replacement_types']; + } + + // }}} + // {{{ getProvideTypes() + + /** + * Get the implemented file replacement types in + * + * @return array + * @static + */ + function getProvideTypes() + { + return $GLOBALS['_PEAR_Common_provide_types']; + } + + // }}} + // {{{ getScriptPhases() + + /** + * Get the implemented file replacement types in + * + * @return array + * @static + */ + function getScriptPhases() + { + return $GLOBALS['_PEAR_Common_script_phases']; + } + + // }}} + // {{{ validPackageName() + + /** + * Test whether a string contains a valid package name. + * + * @param string $name the package name to test + * + * @return bool + * + * @access public + */ + function validPackageName($name) + { + return (bool)preg_match(PEAR_COMMON_PACKAGE_NAME_PREG, $name); + } + + + // }}} + // {{{ validPackageVersion() + + /** + * Test whether a string contains a valid package version. + * + * @param string $ver the package version to test + * + * @return bool + * + * @access public + */ + function validPackageVersion($ver) + { + return (bool)preg_match(PEAR_COMMON_PACKAGE_VERSION_PREG, $ver); + } + + + // }}} + + // {{{ downloadHttp() + + /** + * Download a file through HTTP. Considers suggested file name in + * Content-disposition: header and can run a callback function for + * different events. The callback will be called with two + * parameters: the callback type, and parameters. The implemented + * callback types are: + * + * 'setup' called at the very beginning, parameter is a UI object + * that should be used for all output + * 'message' the parameter is a string with an informational message + * 'saveas' may be used to save with a different file name, the + * parameter is the filename that is about to be used. + * If a 'saveas' callback returns a non-empty string, + * that file name will be used as the filename instead. + * Note that $save_dir will not be affected by this, only + * the basename of the file. + * 'start' download is starting, parameter is number of bytes + * that are expected, or -1 if unknown + * 'bytesread' parameter is the number of bytes read so far + * 'done' download is complete, parameter is the total number + * of bytes read + * 'connfailed' if the TCP connection fails, this callback is called + * with array(host,port,errno,errmsg) + * 'writefailed' if writing to disk fails, this callback is called + * with array(destfile,errmsg) + * + * If an HTTP proxy has been configured (http_proxy PEAR_Config + * setting), the proxy will be used. + * + * @param string $url the URL to download + * @param object $ui PEAR_Frontend_* instance + * @param object $config PEAR_Config instance + * @param string $save_dir (optional) directory to save file in + * @param mixed $callback (optional) function/method to call for status + * updates + * + * @return string Returns the full path of the downloaded file or a PEAR + * error on failure. If the error is caused by + * socket-related errors, the error object will + * have the fsockopen error code available through + * getCode(). + * + * @access public + */ + function downloadHttp($url, &$ui, $save_dir = '.', $callback = null) + { + if ($callback) { + call_user_func($callback, 'setup', array(&$ui)); + } + if (preg_match('!^http://([^/:?#]*)(:(\d+))?(/.*)!', $url, $matches)) { + list(,$host,,$port,$path) = $matches; + } + if (isset($this)) { + $config = &$this->config; + } else { + $config = &PEAR_Config::singleton(); + } + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($proxy = parse_url($config->get('http_proxy'))) { + $proxy_host = @$proxy['host']; + $proxy_port = @$proxy['port']; + $proxy_user = @$proxy['user']; + $proxy_pass = @$proxy['pass']; + + if ($proxy_port == '') { + $proxy_port = 8080; + } + if ($callback) { + call_user_func($callback, 'message', "Using HTTP proxy $host:$port"); + } + } + if (empty($port)) { + $port = 80; + } + if ($proxy_host != '') { + $fp = @fsockopen($proxy_host, $proxy_port, $errno, $errstr); + if (!$fp) { + if ($callback) { + call_user_func($callback, 'connfailed', array($proxy_host, $proxy_port, + $errno, $errstr)); + } + return PEAR::raiseError("Connection to `$proxy_host:$proxy_port' failed: $errstr", $errno); + } + $request = "GET $url HTTP/1.0\r\n"; + } else { + $fp = @fsockopen($host, $port, $errno, $errstr); + if (!$fp) { + if ($callback) { + call_user_func($callback, 'connfailed', array($host, $port, + $errno, $errstr)); + } + return PEAR::raiseError("Connection to `$host:$port' failed: $errstr", $errno); + } + $request = "GET $path HTTP/1.0\r\n"; + } + $request .= "Host: $host:$port\r\n". + "User-Agent: PHP/".PHP_VERSION."\r\n"; + if ($proxy_host != '' && $proxy_user != '') { + $request .= 'Proxy-Authorization: Basic ' . + base64_encode($proxy_user . ':' . $proxy_pass) . "\r\n"; + } + $request .= "\r\n"; + fwrite($fp, $request); + $headers = array(); + while (trim($line = fgets($fp, 1024))) { + if (preg_match('/^([^:]+):\s+(.*)\s*$/', $line, $matches)) { + $headers[strtolower($matches[1])] = trim($matches[2]); + } elseif (preg_match('|^HTTP/1.[01] ([0-9]{3}) |', $line, $matches)) { + if ($matches[1] != 200) { + return PEAR::raiseError("File http://$host:$port$path not valid (received: $line)"); + } + } + } + if (isset($headers['content-disposition']) && + preg_match('/\sfilename=\"([^;]*\S)\"\s*(;|$)/', $headers['content-disposition'], $matches)) { + $save_as = basename($matches[1]); + } else { + $save_as = basename($url); + } + if ($callback) { + $tmp = call_user_func($callback, 'saveas', $save_as); + if ($tmp) { + $save_as = $tmp; + } + } + $dest_file = $save_dir . DIRECTORY_SEPARATOR . $save_as; + if (!$wp = @fopen($dest_file, 'wb')) { + fclose($fp); + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("could not open $dest_file for writing"); + } + if (isset($headers['content-length'])) { + $length = $headers['content-length']; + } else { + $length = -1; + } + $bytes = 0; + if ($callback) { + call_user_func($callback, 'start', array(basename($dest_file), $length)); + } + while ($data = @fread($fp, 1024)) { + $bytes += strlen($data); + if ($callback) { + call_user_func($callback, 'bytesread', $bytes); + } + if (!@fwrite($wp, $data)) { + fclose($fp); + if ($callback) { + call_user_func($callback, 'writefailed', array($dest_file, $php_errormsg)); + } + return PEAR::raiseError("$dest_file: write failed ($php_errormsg)"); + } + } + fclose($fp); + fclose($wp); + if ($callback) { + call_user_func($callback, 'done', $bytes); + } + return $dest_file; + } + + // }}} + // {{{ sortPkgDeps() + + /** + * Sort a list of arrays of array(downloaded packagefilename) by dependency. + * + * It also removes duplicate dependencies + * @param array + * @param boolean Sort packages in reverse order if true + * @return array array of array(packagefilename, package.xml contents) + */ + function sortPkgDeps(&$packages, $uninstall = false) + { + $ret = array(); + if ($uninstall) { + foreach($packages as $packageinfo) { + $ret[] = array('info' => $packageinfo); + } + } else { + foreach($packages as $packagefile) { + if (!is_array($packagefile)) { + $ret[] = array('file' => $packagefile, + 'info' => $a = $this->infoFromAny($packagefile), + 'pkg' => $a['package']); + } else { + $ret[] = $packagefile; + } + } + } + $checkdupes = array(); + $newret = array(); + foreach($ret as $i => $p) { + if (!isset($checkdupes[$p['info']['package']])) { + $checkdupes[$p['info']['package']][] = $i; + $newret[] = $p; + } + } + $this->_packageSortTree = $this->_getPkgDepTree($newret); + + $func = $uninstall ? '_sortPkgDepsRev' : '_sortPkgDeps'; + usort($newret, array(&$this, $func)); + $this->_packageSortTree = null; + $packages = $newret; + } + + // }}} + // {{{ _sortPkgDeps() + + /** + * Compare two package's package.xml, and sort + * so that dependencies are installed first + * + * This is a crude compare, real dependency checking is done on install. + * The only purpose this serves is to make the command-line + * order-independent (you can list a dependent package first, and + * installation occurs in the order required) + * @access private + */ + function _sortPkgDeps($p1, $p2) + { + $p1name = $p1['info']['package']; + $p2name = $p2['info']['package']; + $p1deps = $this->_getPkgDeps($p1); + $p2deps = $this->_getPkgDeps($p2); + if (!count($p1deps) && !count($p2deps)) { + return 0; // order makes no difference + } + if (!count($p1deps)) { + return -1; // package 2 has dependencies, package 1 doesn't + } + if (!count($p2deps)) { + return 1; // package 1 has dependencies, package 2 doesn't + } + // both have dependencies + if (in_array($p1name, $p2deps)) { + return -1; // put package 1 first: package 2 depends on package 1 + } + if (in_array($p2name, $p1deps)) { + return 1; // put package 2 first: package 1 depends on package 2 + } + if ($this->_removedDependency($p1name, $p2name)) { + return -1; // put package 1 first: package 2 depends on packages that depend on package 1 + } + if ($this->_removedDependency($p2name, $p1name)) { + return 1; // put package 2 first: package 1 depends on packages that depend on package 2 + } + // doesn't really matter if neither depends on the other + return 0; + } + + // }}} + // {{{ _sortPkgDepsRev() + + /** + * Compare two package's package.xml, and sort + * so that dependencies are uninstalled last + * + * This is a crude compare, real dependency checking is done on uninstall. + * The only purpose this serves is to make the command-line + * order-independent (you can list a dependency first, and + * uninstallation occurs in the order required) + * @access private + */ + function _sortPkgDepsRev($p1, $p2) + { + $p1name = $p1['info']['package']; + $p2name = $p2['info']['package']; + $p1deps = $this->_getRevPkgDeps($p1); + $p2deps = $this->_getRevPkgDeps($p2); + if (!count($p1deps) && !count($p2deps)) { + return 0; // order makes no difference + } + if (!count($p1deps)) { + return 1; // package 2 has dependencies, package 1 doesn't + } + if (!count($p2deps)) { + return -1; // package 2 has dependencies, package 1 doesn't + } + // both have dependencies + if (in_array($p1name, $p2deps)) { + return 1; // put package 1 last + } + if (in_array($p2name, $p1deps)) { + return -1; // put package 2 last + } + if ($this->_removedDependency($p1name, $p2name)) { + return 1; // put package 1 last: package 2 depends on packages that depend on package 1 + } + if ($this->_removedDependency($p2name, $p1name)) { + return -1; // put package 2 last: package 1 depends on packages that depend on package 2 + } + // doesn't really matter if neither depends on the other + return 0; + } + + // }}} + // {{{ _getPkgDeps() + + /** + * get an array of package dependency names + * @param array + * @return array + * @access private + */ + function _getPkgDeps($p) + { + if (!isset($p['info']['releases'])) { + return $this->_getRevPkgDeps($p); + } + $rel = array_shift($p['info']['releases']); + if (!isset($rel['deps'])) { + return array(); + } + $ret = array(); + foreach($rel['deps'] as $dep) { + if ($dep['type'] == 'pkg') { + $ret[] = $dep['name']; + } + } + return $ret; + } + + // }}} + // {{{ _getPkgDeps() + + /** + * get an array representation of the package dependency tree + * @return array + * @access private + */ + function _getPkgDepTree($packages) + { + $tree = array(); + foreach ($packages as $p) { + $package = $p['info']['package']; + $deps = $this->_getPkgDeps($p); + $tree[$package] = $deps; + } + return $tree; + } + + // }}} + // {{{ _removedDependency($p1, $p2) + + /** + * get an array of package dependency names for uninstall + * @param string package 1 name + * @param string package 2 name + * @return bool + * @access private + */ + function _removedDependency($p1, $p2) + { + if (empty($this->_packageSortTree[$p2])) { + return false; + } + if (!in_array($p1, $this->_packageSortTree[$p2])) { + foreach ($this->_packageSortTree[$p2] as $potential) { + if ($this->_removedDependency($p1, $potential)) { + return true; + } + } + return false; + } + return true; + } + + // }}} + // {{{ _getRevPkgDeps() + + /** + * get an array of package dependency names for uninstall + * @param array + * @return array + * @access private + */ + function _getRevPkgDeps($p) + { + if (!isset($p['info']['release_deps'])) { + return array(); + } + $ret = array(); + foreach($p['info']['release_deps'] as $dep) { + if ($dep['type'] == 'pkg') { + $ret[] = $dep['name']; + } + } + return $ret; + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Config.php b/common/PEAR/PEAR/Config.php new file mode 100644 index 0000000..cea318f --- /dev/null +++ b/common/PEAR/PEAR/Config.php @@ -0,0 +1,1169 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Config.php,v 1.35.2.16 2004/01/26 01:26:46 pajoye Exp $ + +require_once 'PEAR.php'; +require_once 'System.php'; + +/** + * Last created PEAR_Config instance. + * @var object + */ +$GLOBALS['_PEAR_Config_instance'] = null; +if (!defined('PEAR_INSTALL_DIR') || !PEAR_INSTALL_DIR) { + $PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . 'pear'; +} else { + $PEAR_INSTALL_DIR = PEAR_INSTALL_DIR; +} + +// Below we define constants with default values for all configuration +// parameters except username/password. All of them can have their +// defaults set through environment variables. The reason we use the +// PHP_ prefix is for some security, PHP protects environment +// variables starting with PHP_*. + +if (getenv('PHP_PEAR_SYSCONF_DIR')) { + define('PEAR_CONFIG_SYSCONFDIR', getenv('PHP_PEAR_SYSCONF_DIR')); +} elseif (getenv('SystemRoot')) { + define('PEAR_CONFIG_SYSCONFDIR', getenv('SystemRoot')); +} else { + define('PEAR_CONFIG_SYSCONFDIR', PHP_SYSCONFDIR); +} + +// Default for master_server +if (getenv('PHP_PEAR_MASTER_SERVER')) { + define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', getenv('PHP_PEAR_MASTER_SERVER')); +} else { + define('PEAR_CONFIG_DEFAULT_MASTER_SERVER', 'pear.php.net'); +} + +// Default for http_proxy +if (getenv('PHP_PEAR_HTTP_PROXY')) { + define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('PHP_PEAR_HTTP_PROXY')); +} elseif (getenv('http_proxy')) { + define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', getenv('http_proxy')); +} else { + define('PEAR_CONFIG_DEFAULT_HTTP_PROXY', ''); +} + +// Default for php_dir +if (getenv('PHP_PEAR_INSTALL_DIR')) { + define('PEAR_CONFIG_DEFAULT_PHP_DIR', getenv('PHP_PEAR_INSTALL_DIR')); +} else { + if (@is_dir($PEAR_INSTALL_DIR)) { + define('PEAR_CONFIG_DEFAULT_PHP_DIR', + $PEAR_INSTALL_DIR); + } else { + define('PEAR_CONFIG_DEFAULT_PHP_DIR', $PEAR_INSTALL_DIR); + } +} + +// Default for ext_dir +if (getenv('PHP_PEAR_EXTENSION_DIR')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', getenv('PHP_PEAR_EXTENSION_DIR')); +} else { + if (ini_get('extension_dir')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', ini_get('extension_dir')); + } elseif (defined('PEAR_EXTENSION_DIR') && @is_dir(PEAR_EXTENSION_DIR)) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', PEAR_EXTENSION_DIR); + } elseif (defined('PHP_EXTENSION_DIR')) { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', PHP_EXTENSION_DIR); + } else { + define('PEAR_CONFIG_DEFAULT_EXT_DIR', '.'); + } +} + +// Default for doc_dir +if (getenv('PHP_PEAR_DOC_DIR')) { + define('PEAR_CONFIG_DEFAULT_DOC_DIR', getenv('PHP_PEAR_DOC_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_DOC_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'docs'); +} + +// Default for bin_dir +if (getenv('PHP_PEAR_BIN_DIR')) { + define('PEAR_CONFIG_DEFAULT_BIN_DIR', getenv('PHP_PEAR_BIN_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_BIN_DIR', PHP_BINDIR); +} + +// Default for data_dir +if (getenv('PHP_PEAR_DATA_DIR')) { + define('PEAR_CONFIG_DEFAULT_DATA_DIR', getenv('PHP_PEAR_DATA_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_DATA_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'data'); +} + +// Default for test_dir +if (getenv('PHP_PEAR_TEST_DIR')) { + define('PEAR_CONFIG_DEFAULT_TEST_DIR', getenv('PHP_PEAR_TEST_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_TEST_DIR', + $PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.'tests'); +} + +// Default for cache_dir +if (getenv('PHP_PEAR_CACHE_DIR')) { + define('PEAR_CONFIG_DEFAULT_CACHE_DIR', getenv('PHP_PEAR_CACHE_DIR')); +} else { + define('PEAR_CONFIG_DEFAULT_CACHE_DIR', + System::tmpdir() . DIRECTORY_SEPARATOR . 'pear' . + DIRECTORY_SEPARATOR . 'cache'); +} + +// Default for php_bin +if (getenv('PHP_PEAR_PHP_BIN')) { + define('PEAR_CONFIG_DEFAULT_PHP_BIN', getenv('PHP_PEAR_PHP_BIN')); +} else { + define('PEAR_CONFIG_DEFAULT_PHP_BIN', PEAR_CONFIG_DEFAULT_BIN_DIR. + DIRECTORY_SEPARATOR.'php'.(OS_WINDOWS ? '.exe' : '')); +} + +// Default for verbose +if (getenv('PHP_PEAR_VERBOSE')) { + define('PEAR_CONFIG_DEFAULT_VERBOSE', getenv('PHP_PEAR_VERBOSE')); +} else { + define('PEAR_CONFIG_DEFAULT_VERBOSE', 1); +} + +// Default for preferred_state +if (getenv('PHP_PEAR_PREFERRED_STATE')) { + define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', getenv('PHP_PEAR_PREFERRED_STATE')); +} else { + define('PEAR_CONFIG_DEFAULT_PREFERRED_STATE', 'stable'); +} + +// Default for umask +if (getenv('PHP_PEAR_UMASK')) { + define('PEAR_CONFIG_DEFAULT_UMASK', getenv('PHP_PEAR_UMASK')); +} else { + define('PEAR_CONFIG_DEFAULT_UMASK', decoct(umask())); +} + +// Default for cache_ttl +if (getenv('PHP_PEAR_CACHE_TTL')) { + define('PEAR_CONFIG_DEFAULT_CACHE_TTL', getenv('PHP_PEAR_CACHE_TTL')); +} else { + define('PEAR_CONFIG_DEFAULT_CACHE_TTL', 3600); +} + +// Default for sig_type +if (getenv('PHP_PEAR_SIG_TYPE')) { + define('PEAR_CONFIG_DEFAULT_SIG_TYPE', getenv('PHP_PEAR_SIG_TYPE')); +} else { + define('PEAR_CONFIG_DEFAULT_SIG_TYPE', 'gpg'); +} + +// Default for sig_bin +if (getenv('PHP_PEAR_SIG_BIN')) { + define('PEAR_CONFIG_DEFAULT_SIG_BIN', getenv('PHP_PEAR_SIG_BIN')); +} else { + define('PEAR_CONFIG_DEFAULT_SIG_BIN', + System::which( + 'gpg', OS_WINDOWS ? 'c:\gnupg\gpg.exe' : '/usr/local/bin/gpg')); +} + +// Default for sig_keydir +if (getenv('PHP_PEAR_SIG_KEYDIR')) { + define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', getenv('PHP_PEAR_SIG_KEYDIR')); +} else { + define('PEAR_CONFIG_DEFAULT_SIG_KEYDIR', + PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . 'pearkeys'); +} + +/** + * This is a class for storing configuration data, keeping track of + * which are system-defined, user-defined or defaulted. + */ +class PEAR_Config extends PEAR +{ + // {{{ properties + + /** + * Array of config files used. + * + * @var array layer => config file + */ + var $files = array( + 'system' => '', + 'user' => '', + ); + + var $layers = array(); + + /** + * Configuration data, two-dimensional array where the first + * dimension is the config layer ('user', 'system' and 'default'), + * and the second dimension is keyname => value. + * + * The order in the first dimension is important! Earlier + * layers will shadow later ones when a config value is + * requested (if a 'user' value exists, it will be returned first, + * then 'system' and finally 'default'). + * + * @var array layer => array(keyname => value, ...) + */ + var $configuration = array( + 'user' => array(), + 'system' => array(), + 'default' => array(), + ); + + /** + * Information about the configuration data. Stores the type, + * default value and a documentation string for each configuration + * value. + * + * @var array layer => array(infotype => value, ...) + */ + var $configuration_info = array( + // Internet Access + 'master_server' => array( + 'type' => 'string', + 'default' => 'pear.php.net', + 'doc' => 'name of the main PEAR server', + 'prompt' => 'PEAR server', + 'group' => 'Internet Access', + ), + 'http_proxy' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_HTTP_PROXY, + 'doc' => 'HTTP proxy (host:port) to use when downloading packages', + 'prompt' => 'HTTP Proxy Server Address', + 'group' => 'Internet Access', + ), + // File Locations + 'php_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_PHP_DIR, + 'doc' => 'directory where .php files are installed', + 'prompt' => 'PEAR directory', + 'group' => 'File Locations', + ), + 'ext_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_EXT_DIR, + 'doc' => 'directory where loadable extensions are installed', + 'prompt' => 'PHP extension directory', + 'group' => 'File Locations', + ), + 'doc_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_DOC_DIR, + 'doc' => 'directory where documentation is installed', + 'prompt' => 'PEAR documentation directory', + 'group' => 'File Locations', + ), + 'bin_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_BIN_DIR, + 'doc' => 'directory where executables are installed', + 'prompt' => 'PEAR executables directory', + 'group' => 'File Locations', + ), + 'data_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_DATA_DIR, + 'doc' => 'directory where data files are installed', + 'prompt' => 'PEAR data directory', + 'group' => 'File Locations (Advanced)', + ), + 'test_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_TEST_DIR, + 'doc' => 'directory where regression tests are installed', + 'prompt' => 'PEAR test directory', + 'group' => 'File Locations (Advanced)', + ), + 'cache_dir' => array( + 'type' => 'directory', + 'default' => PEAR_CONFIG_DEFAULT_CACHE_DIR, + 'doc' => 'directory which is used for XMLRPC cache', + 'prompt' => 'PEAR Installer cache directory', + 'group' => 'File Locations (Advanced)', + ), + 'php_bin' => array( + 'type' => 'file', + 'default' => PEAR_CONFIG_DEFAULT_PHP_BIN, + 'doc' => 'PHP CLI/CGI binary for executing scripts', + 'prompt' => 'PHP CLI/CGI binary', + 'group' => 'File Locations (Advanced)', + ), + // Maintainers + 'username' => array( + 'type' => 'string', + 'default' => '', + 'doc' => '(maintainers) your PEAR account name', + 'prompt' => 'PEAR username (for maintainers)', + 'group' => 'Maintainers', + ), + 'password' => array( + 'type' => 'password', + 'default' => '', + 'doc' => '(maintainers) your PEAR account password', + 'prompt' => 'PEAR password (for maintainers)', + 'group' => 'Maintainers', + ), + // Advanced + 'verbose' => array( + 'type' => 'integer', + 'default' => PEAR_CONFIG_DEFAULT_VERBOSE, + 'doc' => 'verbosity level +0: really quiet +1: somewhat quiet +2: verbose +3: debug', + 'prompt' => 'Debug Log Level', + 'group' => 'Advanced', + ), + 'preferred_state' => array( + 'type' => 'set', + 'default' => PEAR_CONFIG_DEFAULT_PREFERRED_STATE, + 'doc' => 'the installer will prefer releases with this state when installing packages without a version or state specified', + 'valid_set' => array( + 'stable', 'beta', 'alpha', 'devel', 'snapshot'), + 'prompt' => 'Preferred Package State', + 'group' => 'Advanced', + ), + 'umask' => array( + 'type' => 'mask', + 'default' => PEAR_CONFIG_DEFAULT_UMASK, + 'doc' => 'umask used when creating files (Unix-like systems only)', + 'prompt' => 'Unix file mask', + 'group' => 'Advanced', + ), + 'cache_ttl' => array( + 'type' => 'integer', + 'default' => PEAR_CONFIG_DEFAULT_CACHE_TTL, + 'doc' => 'amount of secs where the local cache is used and not updated', + 'prompt' => 'Cache TimeToLive', + 'group' => 'Advanced', + ), + 'sig_type' => array( + 'type' => 'set', + 'default' => PEAR_CONFIG_DEFAULT_SIG_TYPE, + 'doc' => 'which package signature mechanism to use', + 'valid_set' => array('gpg'), + 'prompt' => 'Package Signature Type', + 'group' => 'Maintainers', + ), + 'sig_bin' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_SIG_BIN, + 'doc' => 'which package signature mechanism to use', + 'prompt' => 'Signature Handling Program', + 'group' => 'Maintainers', + ), + 'sig_keyid' => array( + 'type' => 'string', + 'default' => '', + 'doc' => 'which key to use for signing with', + 'prompt' => 'Signature Key Id', + 'group' => 'Maintainers', + ), + 'sig_keydir' => array( + 'type' => 'string', + 'default' => PEAR_CONFIG_DEFAULT_SIG_KEYDIR, + 'doc' => 'which package signature mechanism to use', + 'prompt' => 'Signature Key Directory', + 'group' => 'Maintainers', + ), + ); + + // }}} + + // {{{ PEAR_Config([file], [defaults_file]) + + /** + * Constructor. + * + * @param string (optional) file to read user-defined options from + * @param string (optional) file to read system-wide defaults from + * + * @access public + * + * @see PEAR_Config::singleton + */ + function PEAR_Config($user_file = '', $system_file = '') + { + $this->PEAR(); + $sl = DIRECTORY_SEPARATOR; + if (empty($user_file)) { + if (OS_WINDOWS) { + $user_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.ini'; + } else { + $user_file = getenv('HOME') . $sl . '.pearrc'; + } + } + if (empty($system_file)) { + if (OS_WINDOWS) { + $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pearsys.ini'; + } else { + $system_file = PEAR_CONFIG_SYSCONFDIR . $sl . 'pear.conf'; + } + } + $this->layers = array_keys($this->configuration); + $this->files['user'] = $user_file; + $this->files['system'] = $system_file; + if ($user_file && file_exists($user_file)) { + $this->readConfigFile($user_file); + } + if ($system_file && file_exists($system_file)) { + $this->mergeConfigFile($system_file, false, 'system'); + } + foreach ($this->configuration_info as $key => $info) { + $this->configuration['default'][$key] = $info['default']; + } + //$GLOBALS['_PEAR_Config_instance'] = &$this; + } + + // }}} + // {{{ singleton([file], [defaults_file]) + + /** + * Static singleton method. If you want to keep only one instance + * of this class in use, this method will give you a reference to + * the last created PEAR_Config object if one exists, or create a + * new object. + * + * @param string (optional) file to read user-defined options from + * @param string (optional) file to read system-wide defaults from + * + * @return object an existing or new PEAR_Config instance + * + * @access public + * + * @see PEAR_Config::PEAR_Config + */ + function &singleton($user_file = '', $system_file = '') + { + if (is_object($GLOBALS['_PEAR_Config_instance'])) { + return $GLOBALS['_PEAR_Config_instance']; + } + $GLOBALS['_PEAR_Config_instance'] = + &new PEAR_Config($user_file, $system_file); + return $GLOBALS['_PEAR_Config_instance']; + } + + // }}} + // {{{ readConfigFile([file], [layer]) + + /** + * Reads configuration data from a file. All existing values in + * the config layer are discarded and replaced with data from the + * file. + * + * @param string (optional) file to read from, if NULL or not + * specified, the last-used file for the same layer (second param) + * is used + * + * @param string (optional) config layer to insert data into + * ('user' or 'system') + * + * @return bool TRUE on success or a PEAR error on failure + * + * @access public + */ + function readConfigFile($file = null, $layer = 'user') + { + if (empty($this->files[$layer])) { + return $this->raiseError("unknown config file type `$layer'"); + } + if ($file === null) { + $file = $this->files[$layer]; + } + $data = $this->_readConfigDataFrom($file); + if (PEAR::isError($data)) { + return $data; + } + $this->_decodeInput($data); + $this->configuration[$layer] = $data; + return true; + } + + // }}} + // {{{ mergeConfigFile(file, [override], [layer]) + + /** + * Merges data into a config layer from a file. Does the same + * thing as readConfigFile, except it does not replace all + * existing values in the config layer. + * + * @param string file to read from + * + * @param bool (optional) whether to overwrite existing data + * (default TRUE) + * + * @param string config layer to insert data into ('user' or + * 'system') + * + * @return bool TRUE on success or a PEAR error on failure + * + * @access public. + */ + function mergeConfigFile($file, $override = true, $layer = 'user') + { + if (empty($this->files[$layer])) { + return $this->raiseError("unknown config file type `$layer'"); + } + if ($file === null) { + $file = $this->files[$layer]; + } + $data = $this->_readConfigDataFrom($file); + if (PEAR::isError($data)) { + return $data; + } + $this->_decodeInput($data); + if ($override) { + $this->configuration[$layer] = array_merge($this->configuration[$layer], $data); + } else { + $this->configuration[$layer] = array_merge($data, $this->configuration[$layer]); + } + return true; + } + + // }}} + // {{{ writeConfigFile([file], [layer]) + + /** + * Writes data into a config layer from a file. + * + * @param string file to read from + * + * @param bool (optional) whether to overwrite existing data + * (default TRUE) + * + * @param string config layer to insert data into ('user' or + * 'system') + * + * @return bool TRUE on success or a PEAR error on failure + * + * @access public. + */ + function writeConfigFile($file = null, $layer = 'user', $data = null) + { + if ($layer == 'both' || $layer == 'all') { + foreach ($this->files as $type => $file) { + $err = $this->writeConfigFile($file, $type, $data); + if (PEAR::isError($err)) { + return $err; + } + } + return true; + } + if (empty($this->files[$layer])) { + return $this->raiseError("unknown config file type `$layer'"); + } + if ($file === null) { + $file = $this->files[$layer]; + } + $data = ($data === null) ? $this->configuration[$layer] : $data; + $this->_encodeOutput($data); + $opt = array('-p', dirname($file)); + if (!@System::mkDir($opt)) { + return $this->raiseError("could not create directory: " . dirname($file)); + } + if (@is_file($file) && !@is_writeable($file)) { + return $this->raiseError("no write access to $file!"); + } + $fp = @fopen($file, "w"); + if (!$fp) { + return $this->raiseError("PEAR_Config::writeConfigFile fopen('$file','w') failed"); + } + $contents = "#PEAR_Config 0.9\n" . serialize($data); + if (!@fwrite($fp, $contents)) { + return $this->raiseError("PEAR_Config::writeConfigFile: fwrite failed"); + } + return true; + } + + // }}} + // {{{ _readConfigDataFrom(file) + + /** + * Reads configuration data from a file and returns the parsed data + * in an array. + * + * @param string file to read from + * + * @return array configuration data or a PEAR error on failure + * + * @access private + */ + function _readConfigDataFrom($file) + { + $fp = @fopen($file, "r"); + if (!$fp) { + return $this->raiseError("PEAR_Config::readConfigFile fopen('$file','r') failed"); + } + $size = filesize($file); + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + $contents = fread($fp, $size); + set_magic_quotes_runtime($rt); + fclose($fp); + $version = '0.1'; + if (preg_match('/^#PEAR_Config\s+(\S+)\s+/si', $contents, $matches)) { + $version = $matches[1]; + $contents = substr($contents, strlen($matches[0])); + } + if (version_compare("$version", '1', '<')) { + $data = unserialize($contents); + if (!is_array($data)) { + if (strlen(trim($contents)) > 0) { + $error = "PEAR_Config: bad data in $file"; +// if (isset($this)) { + return $this->raiseError($error); +// } else { +// return PEAR::raiseError($error); + } else { + $data = array(); + } + } + // add parsing of newer formats here... + } else { + return $this->raiseError("$file: unknown version `$version'"); + } + return $data; + } + + // }}} + // {{{ getConfFile(layer) + /** + * Gets the file used for storing the config for a layer + * + * @param string $layer 'user' or 'system' + */ + + function getConfFile($layer) + { + return $this->files[$layer]; + } + + // }}} + // {{{ _encodeOutput(&data) + + /** + * Encodes/scrambles configuration data before writing to files. + * Currently, 'password' values will be base64-encoded as to avoid + * that people spot cleartext passwords by accident. + * + * @param array (reference) array to encode values in + * + * @return bool TRUE on success + * + * @access private + */ + function _encodeOutput(&$data) + { + foreach ($data as $key => $value) { + if (!isset($this->configuration_info[$key])) { + continue; + } + $type = $this->configuration_info[$key]['type']; + switch ($type) { + // we base64-encode passwords so they are at least + // not shown in plain by accident + case 'password': { + $data[$key] = base64_encode($data[$key]); + break; + } + case 'mask': { + $data[$key] = octdec($data[$key]); + break; + } + } + } + return true; + } + + // }}} + // {{{ _decodeInput(&data) + + /** + * Decodes/unscrambles configuration data after reading from files. + * + * @param array (reference) array to encode values in + * + * @return bool TRUE on success + * + * @access private + * + * @see PEAR_Config::_encodeOutput + */ + function _decodeInput(&$data) + { + if (!is_array($data)) { + return true; + } + foreach ($data as $key => $value) { + if (!isset($this->configuration_info[$key])) { + continue; + } + $type = $this->configuration_info[$key]['type']; + switch ($type) { + case 'password': { + $data[$key] = base64_decode($data[$key]); + break; + } + case 'mask': { + $data[$key] = decoct($data[$key]); + break; + } + } + } + return true; + } + + // }}} + // {{{ get(key, [layer]) + + /** + * Returns a configuration value, prioritizing layers as per the + * layers property. + * + * @param string config key + * + * @return mixed the config value, or NULL if not found + * + * @access public + */ + function get($key, $layer = null) + { + if ($layer === null) { + foreach ($this->layers as $layer) { + if (isset($this->configuration[$layer][$key])) { + return $this->configuration[$layer][$key]; + } + } + } elseif (isset($this->configuration[$layer][$key])) { + return $this->configuration[$layer][$key]; + } + return null; + } + + // }}} + // {{{ set(key, value, [layer]) + + /** + * Set a config value in a specific layer (defaults to 'user'). + * Enforces the types defined in the configuration_info array. An + * integer config variable will be cast to int, and a set config + * variable will be validated against its legal values. + * + * @param string config key + * + * @param string config value + * + * @param string (optional) config layer + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function set($key, $value, $layer = 'user') + { + if (empty($this->configuration_info[$key])) { + return false; + } + extract($this->configuration_info[$key]); + switch ($type) { + case 'integer': + $value = (int)$value; + break; + case 'set': { + // If a valid_set is specified, require the value to + // be in the set. If there is no valid_set, accept + // any value. + if ($valid_set) { + reset($valid_set); + if ((key($valid_set) === 0 && !in_array($value, $valid_set)) || + (key($valid_set) !== 0 && empty($valid_set[$value]))) + { + return false; + } + } + break; + } + } + $this->configuration[$layer][$key] = $value; + return true; + } + + // }}} + // {{{ getType(key) + + /** + * Get the type of a config value. + * + * @param string config key + * + * @return string type, one of "string", "integer", "file", + * "directory", "set" or "password". + * + * @access public + * + */ + function getType($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['type']; + } + return false; + } + + // }}} + // {{{ getDocs(key) + + /** + * Get the documentation for a config value. + * + * @param string config key + * + * @return string documentation string + * + * @access public + * + */ + function getDocs($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['doc']; + } + return false; + } + // }}} + // {{{ getPrompt(key) + + /** + * Get the short documentation for a config value. + * + * @param string config key + * + * @return string short documentation string + * + * @access public + * + */ + function getPrompt($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['prompt']; + } + return false; + } + // }}} + // {{{ getGroup(key) + + /** + * Get the parameter group for a config key. + * + * @param string config key + * + * @return string parameter group + * + * @access public + * + */ + function getGroup($key) + { + if (isset($this->configuration_info[$key])) { + return $this->configuration_info[$key]['group']; + } + return false; + } + + // }}} + // {{{ getGroups() + + /** + * Get the list of parameter groups. + * + * @return array list of parameter groups + * + * @access public + * + */ + function getGroups() + { + $tmp = array(); + foreach ($this->configuration_info as $key => $info) { + $tmp[$info['group']] = 1; + } + return array_keys($tmp); + } + + // }}} + // {{{ getGroupKeys() + + /** + * Get the list of the parameters in a group. + * + * @param string $group parameter group + * + * @return array list of parameters in $group + * + * @access public + * + */ + function getGroupKeys($group) + { + $keys = array(); + foreach ($this->configuration_info as $key => $info) { + if ($info['group'] == $group) { + $keys[] = $key; + } + } + return $keys; + } + + // }}} + // {{{ getSetValues(key) + + /** + * Get the list of allowed set values for a config value. Returns + * NULL for config values that are not sets. + * + * @param string config key + * + * @return array enumerated array of set values, or NULL if the + * config key is unknown or not a set + * + * @access public + * + */ + function getSetValues($key) + { + if (isset($this->configuration_info[$key]) && + isset($this->configuration_info[$key]['type']) && + $this->configuration_info[$key]['type'] == 'set') + { + $valid_set = $this->configuration_info[$key]['valid_set']; + reset($valid_set); + if (key($valid_set) === 0) { + return $valid_set; + } + return array_keys($valid_set); + } + return false; + } + + // }}} + // {{{ getKeys() + + /** + * Get all the current config keys. + * + * @return array simple array of config keys + * + * @access public + */ + function getKeys() + { + $keys = array(); + foreach ($this->layers as $layer) { + $keys = array_merge($keys, $this->configuration[$layer]); + } + return array_keys($keys); + } + + // }}} + // {{{ remove(key, [layer]) + + /** + * Remove the a config key from a specific config layer. + * + * @param string config key + * + * @param string (optional) config layer + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function remove($key, $layer = 'user') + { + if (isset($this->configuration[$layer][$key])) { + unset($this->configuration[$layer][$key]); + return true; + } + return false; + } + + // }}} + // {{{ removeLayer(layer) + + /** + * Temporarily remove an entire config layer. USE WITH CARE! + * + * @param string config key + * + * @param string (optional) config layer + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function removeLayer($layer) + { + if (isset($this->configuration[$layer])) { + $this->configuration[$layer] = array(); + return true; + } + return false; + } + + // }}} + // {{{ store([layer]) + + /** + * Stores configuration data in a layer. + * + * @param string config layer to store + * + * @return bool TRUE on success, or PEAR error on failure + * + * @access public + */ + function store($layer = 'user', $data = null) + { + return $this->writeConfigFile(null, $layer, $data); + } + + // }}} + // {{{ toDefault(key) + + /** + * Unset the user-defined value of a config key, reverting the + * value to the system-defined one. + * + * @param string config key + * + * @return bool TRUE on success, FALSE on failure + * + * @access public + */ + function toDefault($key) + { + trigger_error("PEAR_Config::toDefault() deprecated, use PEAR_Config::remove() instead", E_USER_NOTICE); + return $this->remove($key, 'user'); + } + + // }}} + // {{{ definedBy(key) + + /** + * Tells what config layer that gets to define a key. + * + * @param string config key + * + * @return string the config layer, or an empty string if not found + * + * @access public + */ + function definedBy($key) + { + foreach ($this->layers as $layer) { + if (isset($this->configuration[$layer][$key])) { + return $layer; + } + } + return ''; + } + + // }}} + // {{{ isDefaulted(key) + + /** + * Tells whether a config value has a system-defined value. + * + * @param string config key + * + * @return bool + * + * @access public + * + * @deprecated + */ + function isDefaulted($key) + { + trigger_error("PEAR_Config::isDefaulted() deprecated, use PEAR_Config::definedBy() instead", E_USER_NOTICE); + return $this->definedBy($key) == 'system'; + } + + // }}} + // {{{ isDefined(key) + + /** + * Tells whether a given key exists as a config value. + * + * @param string config key + * + * @return bool whether exists in this object + * + * @access public + */ + function isDefined($key) + { + foreach ($this->layers as $layer) { + if (isset($this->configuration[$layer][$key])) { + return true; + } + } + return false; + } + + // }}} + // {{{ isDefinedLayer(key) + + /** + * Tells whether a given config layer exists. + * + * @param string config layer + * + * @return bool whether exists in this object + * + * @access public + */ + function isDefinedLayer($layer) + { + return isset($this->configuration[$layer]); + } + + // }}} + // {{{ getLayers() + + /** + * Returns the layers defined (except the 'default' one) + * + * @return array of the defined layers + */ + function getLayers() + { + $cf = $this->configuration; + unset($cf['default']); + return array_keys($cf); + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Dependency.php b/common/PEAR/PEAR/Dependency.php new file mode 100644 index 0000000..8b0d438 --- /dev/null +++ b/common/PEAR/PEAR/Dependency.php @@ -0,0 +1,486 @@ + | +// | Stig Bakken | +// +----------------------------------------------------------------------+ +// +// $Id: Dependency.php,v 1.14.4.20 2004/01/26 01:26:46 pajoye Exp $ + +require_once "PEAR.php"; + +define('PEAR_DEPENDENCY_MISSING', -1); +define('PEAR_DEPENDENCY_CONFLICT', -2); +define('PEAR_DEPENDENCY_UPGRADE_MINOR', -3); +define('PEAR_DEPENDENCY_UPGRADE_MAJOR', -4); +define('PEAR_DEPENDENCY_BAD_DEPENDENCY', -5); +define('PEAR_DEPENDENCY_MISSING_OPTIONAL', -6); +define('PEAR_DEPENDENCY_CONFLICT_OPTIONAL', -7); +define('PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL', -8); +define('PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL', -9); + +/** + * Dependency check for PEAR packages + * + * The class is based on the dependency RFC that can be found at + * http://cvs.php.net/cvs.php/pearweb/rfc. It requires PHP >= 4.1 + * + * @author Tomas V.V.Vox + * @author Stig Bakken + */ +class PEAR_Dependency +{ + // {{{ constructor + /** + * Constructor + * + * @access public + * @param object Registry object + * @return void + */ + function PEAR_Dependency(&$registry) + { + $this->registry = &$registry; + } + + // }}} + // {{{ callCheckMethod() + + /** + * This method maps the XML dependency definition to the + * corresponding one from PEAR_Dependency + * + *
+    * $opts => Array
+    *    (
+    *        [type] => pkg
+    *        [rel] => ge
+    *        [version] => 3.4
+    *        [name] => HTML_Common
+    *        [optional] => false
+    *    )
+    * 
+ * + * @param string Error message + * @param array Options + * @return boolean + */ + function callCheckMethod(&$errmsg, $opts) + { + $rel = isset($opts['rel']) ? $opts['rel'] : 'has'; + $req = isset($opts['version']) ? $opts['version'] : null; + $name = isset($opts['name']) ? $opts['name'] : null; + $opt = (isset($opts['optional']) && $opts['optional'] == 'yes') ? + $opts['optional'] : null; + $errmsg = ''; + switch ($opts['type']) { + case 'pkg': + return $this->checkPackage($errmsg, $name, $req, $rel, $opt); + break; + case 'ext': + return $this->checkExtension($errmsg, $name, $req, $rel, $opt); + break; + case 'php': + return $this->checkPHP($errmsg, $req, $rel); + break; + case 'prog': + return $this->checkProgram($errmsg, $name); + break; + case 'os': + return $this->checkOS($errmsg, $name); + break; + case 'sapi': + return $this->checkSAPI($errmsg, $name); + break; + case 'zend': + return $this->checkZend($errmsg, $name); + break; + default: + return "'{$opts['type']}' dependency type not supported"; + } + } + + // }}} + // {{{ checkPackage() + + /** + * Package dependencies check method + * + * @param string $errmsg Empty string, it will be populated with an error message, if any + * @param string $name Name of the package to test + * @param string $req The package version required + * @param string $relation How to compare versions with each other + * @param bool $opt Whether the relationship is optional + * + * @return mixed bool false if no error or the error string + */ + function checkPackage(&$errmsg, $name, $req = null, $relation = 'has', + $opt = false) + { + if (is_string($req) && substr($req, 0, 2) == 'v.') { + $req = substr($req, 2); + } + switch ($relation) { + case 'has': + if (!$this->registry->packageExists($name)) { + if ($opt) { + $errmsg = "package `$name' is recommended to utilize some features."; + return PEAR_DEPENDENCY_MISSING_OPTIONAL; + } + $errmsg = "requires package `$name'"; + return PEAR_DEPENDENCY_MISSING; + } + return false; + case 'not': + if ($this->registry->packageExists($name)) { + $errmsg = "conflicts with package `$name'"; + return PEAR_DEPENDENCY_CONFLICT; + } + return false; + case 'lt': + case 'le': + case 'eq': + case 'ne': + case 'ge': + case 'gt': + $version = $this->registry->packageInfo($name, 'version'); + if (!$this->registry->packageExists($name) + || !version_compare("$version", "$req", $relation)) + { + $code = $this->codeFromRelation($relation, $version, $req, $opt); + if ($opt) { + $errmsg = "package `$name' version " . $this->signOperator($relation) . + " $req is recommended to utilize some features."; + if ($version) { + $errmsg .= " Installed version is $version"; + } + return $code; + } + $errmsg = "requires package `$name' " . + $this->signOperator($relation) . " $req"; + return $code; + } + return false; + } + $errmsg = "relation '$relation' with requirement '$req' is not supported (name=$name)"; + return PEAR_DEPENDENCY_BAD_DEPENDENCY; + } + + // }}} + // {{{ checkPackageUninstall() + + /** + * Check package dependencies on uninstall + * + * @param string $error The resultant error string + * @param string $warning The resultant warning string + * @param string $name Name of the package to test + * + * @return bool true if there were errors + */ + function checkPackageUninstall(&$error, &$warning, $package) + { + $error = null; + $packages = $this->registry->listPackages(); + foreach ($packages as $pkg) { + if ($pkg == $package) { + continue; + } + $deps = $this->registry->packageInfo($pkg, 'release_deps'); + if (empty($deps)) { + continue; + } + foreach ($deps as $dep) { + if ($dep['type'] == 'pkg' && strcasecmp($dep['name'], $package) == 0) { + if ($dep['rel'] == 'ne') { + continue; + } + if (isset($dep['optional']) && $dep['optional'] == 'yes') { + $warning .= "\nWarning: Package '$pkg' optionally depends on '$package'"; + } else { + $error .= "Package '$pkg' depends on '$package'\n"; + } + } + } + } + return ($error) ? true : false; + } + + // }}} + // {{{ checkExtension() + + /** + * Extension dependencies check method + * + * @param string $name Name of the extension to test + * @param string $req_ext_ver Required extension version to compare with + * @param string $relation How to compare versions with eachother + * @param bool $opt Whether the relationship is optional + * + * @return mixed bool false if no error or the error string + */ + function checkExtension(&$errmsg, $name, $req = null, $relation = 'has', + $opt = false) + { + if ($relation == 'not') { + if (extension_loaded($name)) { + $errmsg = "conflicts with PHP extension '$name'"; + return PEAR_DEPENDENCY_CONFLICT; + } else { + return false; + } + } + + if (!extension_loaded($name)) { + if ($relation == 'ne') { + return false; + } + if ($opt) { + $errmsg = "'$name' PHP extension is recommended to utilize some features"; + return PEAR_DEPENDENCY_MISSING_OPTIONAL; + } + $errmsg = "'$name' PHP extension is not installed"; + return PEAR_DEPENDENCY_MISSING; + } + if ($relation == 'has') { + return false; + } + $code = false; + if (is_string($req) && substr($req, 0, 2) == 'v.') { + $req = substr($req, 2); + } + $ext_ver = phpversion($name); + $operator = $relation; + // Force params to be strings, otherwise the comparation will fail (ex. 0.9==0.90) + if (!version_compare("$ext_ver", "$req", $operator)) { + $errmsg = "'$name' PHP extension version " . + $this->signOperator($operator) . " $req is required"; + $code = $this->codeFromRelation($relation, $ext_ver, $req, $opt); + if ($opt) { + $errmsg = "'$name' PHP extension version " . $this->signOperator($operator) . + " $req is recommended to utilize some features"; + return $code; + } + } + return $code; + } + + // }}} + // {{{ checkOS() + + /** + * Operating system dependencies check method + * + * @param string $os Name of the operating system + * + * @return mixed bool false if no error or the error string + */ + function checkOS(&$errmsg, $os) + { + // XXX Fixme: Implement a more flexible way, like + // comma separated values or something similar to PEAR_OS + static $myos; + if (empty($myos)) { + include_once "OS/Guess.php"; + $myos = new OS_Guess(); + } + // only 'has' relation is currently supported + if ($myos->matchSignature($os)) { + return false; + } + $errmsg = "'$os' operating system not supported"; + return PEAR_DEPENDENCY_CONFLICT; + } + + // }}} + // {{{ checkPHP() + + /** + * PHP version check method + * + * @param string $req which version to compare + * @param string $relation how to compare the version + * + * @return mixed bool false if no error or the error string + */ + function checkPHP(&$errmsg, $req, $relation = 'ge') + { + // this would be a bit stupid, but oh well :) + if ($relation == 'has') { + return false; + } + if ($relation == 'not') { + $errmsg = "Invalid dependency - 'not' is allowed when specifying PHP, you must run PHP in PHP"; + return PEAR_DEPENDENCY_BAD_DEPENDENCY; + } + if (substr($req, 0, 2) == 'v.') { + $req = substr($req,2, strlen($req) - 2); + } + $php_ver = phpversion(); + $operator = $relation; + if (!version_compare("$php_ver", "$req", $operator)) { + $errmsg = "PHP version " . $this->signOperator($operator) . + " $req is required"; + return PEAR_DEPENDENCY_CONFLICT; + } + return false; + } + + // }}} + // {{{ checkProgram() + + /** + * External program check method. Looks for executable files in + * directories listed in the PATH environment variable. + * + * @param string $program which program to look for + * + * @return mixed bool false if no error or the error string + */ + function checkProgram(&$errmsg, $program) + { + // XXX FIXME honor safe mode + $exe_suffix = OS_WINDOWS ? '.exe' : ''; + $path_elements = explode(PATH_SEPARATOR, getenv('PATH')); + foreach ($path_elements as $dir) { + $file = $dir . DIRECTORY_SEPARATOR . $program . $exe_suffix; + if (@file_exists($file) && @is_executable($file)) { + return false; + } + } + $errmsg = "'$program' program is not present in the PATH"; + return PEAR_DEPENDENCY_MISSING; + } + + // }}} + // {{{ checkSAPI() + + /** + * SAPI backend check method. Version comparison is not yet + * available here. + * + * @param string $name name of SAPI backend + * @param string $req which version to compare + * @param string $relation how to compare versions (currently + * hardcoded to 'has') + * @return mixed bool false if no error or the error string + */ + function checkSAPI(&$errmsg, $name, $req = null, $relation = 'has') + { + // XXX Fixme: There is no way to know if the user has or + // not other SAPI backends installed than the installer one + + $sapi_backend = php_sapi_name(); + // Version comparisons not supported, sapi backends don't have + // version information yet. + if ($sapi_backend == $name) { + return false; + } + $errmsg = "'$sapi_backend' SAPI backend not supported"; + return PEAR_DEPENDENCY_CONFLICT; + } + + // }}} + // {{{ checkZend() + + /** + * Zend version check method + * + * @param string $req which version to compare + * @param string $relation how to compare the version + * + * @return mixed bool false if no error or the error string + */ + function checkZend(&$errmsg, $req, $relation = 'ge') + { + if (substr($req, 0, 2) == 'v.') { + $req = substr($req,2, strlen($req) - 2); + } + $zend_ver = zend_version(); + $operator = substr($relation,0,2); + if (!version_compare("$zend_ver", "$req", $operator)) { + $errmsg = "Zend version " . $this->signOperator($operator) . + " $req is required"; + return PEAR_DEPENDENCY_CONFLICT; + } + return false; + } + + // }}} + // {{{ signOperator() + + /** + * Converts text comparing operators to them sign equivalents + * + * Example: 'ge' to '>=' + * + * @access public + * @param string Operator + * @return string Sign equivalent + */ + function signOperator($operator) + { + switch($operator) { + case 'lt': return '<'; + case 'le': return '<='; + case 'gt': return '>'; + case 'ge': return '>='; + case 'eq': return '=='; + case 'ne': return '!='; + default: + return $operator; + } + } + + // }}} + // {{{ codeFromRelation() + + /** + * Convert relation into corresponding code + * + * @access public + * @param string Relation + * @param string Version + * @param string Requirement + * @param bool Optional dependency indicator + * @return integer + */ + function codeFromRelation($relation, $version, $req, $opt = false) + { + $code = PEAR_DEPENDENCY_BAD_DEPENDENCY; + switch ($relation) { + case 'gt': case 'ge': case 'eq': + // upgrade + $have_major = preg_replace('/\D.*/', '', $version); + $need_major = preg_replace('/\D.*/', '', $req); + if ($need_major > $have_major) { + $code = $opt ? PEAR_DEPENDENCY_UPGRADE_MAJOR_OPTIONAL : + PEAR_DEPENDENCY_UPGRADE_MAJOR; + } else { + $code = $opt ? PEAR_DEPENDENCY_UPGRADE_MINOR_OPTIONAL : + PEAR_DEPENDENCY_UPGRADE_MINOR; + } + break; + case 'lt': case 'le': case 'ne': + $code = $opt ? PEAR_DEPENDENCY_CONFLICT_OPTIONAL : + PEAR_DEPENDENCY_CONFLICT; + break; + } + return $code; + } + + // }}} +} +?> diff --git a/common/PEAR/PEAR/Downloader.php b/common/PEAR/PEAR/Downloader.php new file mode 100644 index 0000000..e248367 --- /dev/null +++ b/common/PEAR/PEAR/Downloader.php @@ -0,0 +1,665 @@ + | +// | Tomas V.V.Cox | +// | Martin Jansen | +// +----------------------------------------------------------------------+ +// +// $Id: Downloader.php,v 1.9.2.7 2004/04/30 16:37:40 cellog Exp $ + +require_once 'PEAR/Common.php'; +require_once 'PEAR/Registry.php'; +require_once 'PEAR/Dependency.php'; +require_once 'PEAR/Remote.php'; +require_once 'System.php'; + + +define('PEAR_INSTALLER_OK', 1); +define('PEAR_INSTALLER_FAILED', 0); +define('PEAR_INSTALLER_SKIPPED', -1); +define('PEAR_INSTALLER_ERROR_NO_PREF_STATE', 2); + +/** + * Administration class used to download PEAR packages and maintain the + * installed package database. + * + * @since PEAR 1.4 + * @author Greg Beaver + */ +class PEAR_Downloader extends PEAR_Common +{ + /** + * @var PEAR_Config + * @access private + */ + var $_config; + + /** + * @var PEAR_Registry + * @access private + */ + var $_registry; + + /** + * @var PEAR_Remote + * @access private + */ + var $_remote; + + /** + * Preferred Installation State (snapshot, devel, alpha, beta, stable) + * @var string|null + * @access private + */ + var $_preferredState; + + /** + * Options from command-line passed to Install. + * + * Recognized options:
+ * - onlyreqdeps : install all required dependencies as well + * - alldeps : install all dependencies, including optional + * - installroot : base relative path to install files in + * - force : force a download even if warnings would prevent it + * @see PEAR_Command_Install + * @access private + * @var array + */ + var $_options; + + /** + * Downloaded Packages after a call to download(). + * + * Format of each entry: + * + * + * array('pkg' => 'package_name', 'file' => '/path/to/local/file', + * 'info' => array() // parsed package.xml + * ); + * + * @access private + * @var array + */ + var $_downloadedPackages = array(); + + /** + * Packages slated for download. + * + * This is used to prevent downloading a package more than once should it be a dependency + * for two packages to be installed. + * Format of each entry: + * + *
+     * array('package_name1' => parsed package.xml, 'package_name2' => parsed package.xml,
+     * );
+     * 
+ * @access private + * @var array + */ + var $_toDownload = array(); + + /** + * Array of every package installed, with names lower-cased. + * + * Format: + * + * array('package1' => 0, 'package2' => 1, ); + * + * @var array + */ + var $_installed = array(); + + /** + * @var array + * @access private + */ + var $_errorStack = array(); + + // {{{ PEAR_Downloader() + + function PEAR_Downloader(&$ui, $options, &$config) + { + $this->_options = $options; + $this->_config = &$config; + $this->_preferredState = $this->_config->get('preferred_state'); + $this->ui = &$ui; + if (!$this->_preferredState) { + // don't inadvertantly use a non-set preferred_state + $this->_preferredState = null; + } + + $php_dir = $this->_config->get('php_dir'); + if (isset($this->_options['installroot'])) { + if (substr($this->_options['installroot'], -1) == DIRECTORY_SEPARATOR) { + $this->_options['installroot'] = substr($this->_options['installroot'], 0, -1); + } + $php_dir = $this->_prependPath($php_dir, $this->_options['installroot']); + } + $this->_registry = &new PEAR_Registry($php_dir); + $this->_remote = &new PEAR_Remote($config); + + if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) { + $this->_installed = $this->_registry->listPackages(); + array_walk($this->_installed, create_function('&$v,$k','$v = strtolower($v);')); + $this->_installed = array_flip($this->_installed); + } + parent::PEAR_Common(); + } + + // }}} + // {{{ configSet() + function configSet($key, $value, $layer = 'user') + { + $this->_config->set($key, $value, $layer); + $this->_preferredState = $this->_config->get('preferred_state'); + if (!$this->_preferredState) { + // don't inadvertantly use a non-set preferred_state + $this->_preferredState = null; + } + } + + // }}} + // {{{ setOptions() + function setOptions($options) + { + $this->_options = $options; + } + + // }}} + // {{{ _downloadFile() + /** + * @param string filename to download + * @param string version/state + * @param string original value passed to command-line + * @param string|null preferred state (snapshot/devel/alpha/beta/stable) + * Defaults to configuration preferred state + * @return null|PEAR_Error|string + * @access private + */ + function _downloadFile($pkgfile, $version, $origpkgfile, $state = null) + { + if (is_null($state)) { + $state = $this->_preferredState; + } + // {{{ check the package filename, and whether it's already installed + $need_download = false; + if (preg_match('#^(http|ftp)://#', $pkgfile)) { + $need_download = true; + } elseif (!@is_file($pkgfile)) { + if ($this->validPackageName($pkgfile)) { + if ($this->_registry->packageExists($pkgfile)) { + if (empty($this->_options['upgrade']) && empty($this->_options['force'])) { + $errors[] = "$pkgfile already installed"; + return; + } + } + $pkgfile = $this->getPackageDownloadUrl($pkgfile, $version); + $need_download = true; + } else { + if (strlen($pkgfile)) { + $errors[] = "Could not open the package file: $pkgfile"; + } else { + $errors[] = "No package file given"; + } + return; + } + } + // }}} + + // {{{ Download package ----------------------------------------------- + if ($need_download) { + $downloaddir = $this->_config->get('download_dir'); + if (empty($downloaddir)) { + if (PEAR::isError($downloaddir = System::mktemp('-d'))) { + return $downloaddir; + } + $this->log(3, '+ tmp dir created at ' . $downloaddir); + } + $callback = $this->ui ? array(&$this, '_downloadCallback') : null; + $this->pushErrorHandling(PEAR_ERROR_RETURN); + $file = $this->downloadHttp($pkgfile, $this->ui, $downloaddir, $callback); + $this->popErrorHandling(); + if (PEAR::isError($file)) { + if ($this->validPackageName($origpkgfile)) { + if (!PEAR::isError($info = $this->_remote->call('package.info', + $origpkgfile))) { + if (!count($info['releases'])) { + return $this->raiseError('Package ' . $origpkgfile . + ' has no releases'); + } else { + return $this->raiseError('No releases of preferred state "' + . $state . '" exist for package ' . $origpkgfile . + '. Use ' . $origpkgfile . '-state to install another' . + ' state (like ' . $origpkgfile .'-beta)', + PEAR_INSTALLER_ERROR_NO_PREF_STATE); + } + } else { + return $pkgfile; + } + } else { + return $this->raiseError($file); + } + } + $pkgfile = $file; + } + // }}} + return $pkgfile; + } + // }}} + // {{{ getPackageDownloadUrl() + + function getPackageDownloadUrl($package, $version = null) + { + if ($version) { + $package .= "-$version"; + } + if ($this === null || $this->_config === null) { + $package = "http://pear.php.net/get/$package"; + } else { + $package = "http://" . $this->_config->get('master_server') . + "/get/$package"; + } + if (!extension_loaded("zlib")) { + $package .= '?uncompress=yes'; + } + return $package; + } + + // }}} + // {{{ extractDownloadFileName($pkgfile, &$version) + + function extractDownloadFileName($pkgfile, &$version) + { + if (@is_file($pkgfile)) { + return $pkgfile; + } + // regex defined in Common.php + if (preg_match(PEAR_COMMON_PACKAGE_DOWNLOAD_PREG, $pkgfile, $m)) { + $version = (isset($m[3])) ? $m[3] : null; + return $m[1]; + } + $version = null; + return $pkgfile; + } + + // }}} + + // }}} + // {{{ getDownloadedPackages() + + /** + * Retrieve a list of downloaded packages after a call to {@link download()}. + * + * Also resets the list of downloaded packages. + * @return array + */ + function getDownloadedPackages() + { + $ret = $this->_downloadedPackages; + $this->_downloadedPackages = array(); + $this->_toDownload = array(); + return $ret; + } + + // }}} + // {{{ download() + + /** + * Download any files and their dependencies, if necessary + * + * BC-compatible method name + * @param array a mixed list of package names, local files, or package.xml + */ + function download($packages) + { + return $this->doDownload($packages); + } + + // }}} + // {{{ doDownload() + + /** + * Download any files and their dependencies, if necessary + * + * @param array a mixed list of package names, local files, or package.xml + */ + function doDownload($packages) + { + $mywillinstall = array(); + $state = $this->_preferredState; + + // {{{ download files in this list if necessary + foreach($packages as $pkgfile) { + $need_download = false; + if (!is_file($pkgfile)) { + if (preg_match('#^(http|ftp)://#', $pkgfile)) { + $need_download = true; + } + $pkgfile = $this->_downloadNonFile($pkgfile); + if (PEAR::isError($pkgfile)) { + return $pkgfile; + } + if ($pkgfile === false) { + continue; + } + } // end is_file() + + $tempinfo = $this->infoFromAny($pkgfile); + if ($need_download) { + $this->_toDownload[] = $tempinfo['package']; + } + if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) { + // ignore dependencies if there are any errors + if (!PEAR::isError($tempinfo)) { + $mywillinstall[strtolower($tempinfo['package'])] = @$tempinfo['release_deps']; + } + } + $this->_downloadedPackages[] = array('pkg' => $tempinfo['package'], + 'file' => $pkgfile, 'info' => $tempinfo); + } // end foreach($packages) + // }}} + + // {{{ extract dependencies from downloaded files and then download + // them if necessary + if (isset($this->_options['alldeps']) || isset($this->_options['onlyreqdeps'])) { + $deppackages = array(); + foreach ($mywillinstall as $package => $alldeps) { + if (!is_array($alldeps)) { + // there are no dependencies + continue; + } + foreach($alldeps as $info) { + if ($info['type'] != 'pkg') { + continue; + } + $ret = $this->_processDependency($package, $info, $mywillinstall); + if ($ret === false) { + continue; + } + if (PEAR::isError($ret)) { + return $ret; + } + $deppackages[] = $ret; + } // foreach($alldeps + } + + if (count($deppackages)) { + $this->doDownload($deppackages); + } + } // }}} if --alldeps or --onlyreqdeps + } + + // }}} + // {{{ _downloadNonFile($pkgfile) + + /** + * @return false|PEAR_Error|string false if loop should be broken out of, + * string if the file was downloaded, + * PEAR_Error on exception + * @access private + */ + function _downloadNonFile($pkgfile) + { + $origpkgfile = $pkgfile; + $state = null; + $pkgfile = $this->extractDownloadFileName($pkgfile, $version); + if (preg_match('#^(http|ftp)://#', $pkgfile)) { + return $this->_downloadFile($pkgfile, $version, $origpkgfile); + } + if (!$this->validPackageName($pkgfile)) { + return $this->raiseError("Package name '$pkgfile' not valid"); + } + // ignore packages that are installed unless we are upgrading + $curinfo = $this->_registry->packageInfo($pkgfile); + if ($this->_registry->packageExists($pkgfile) + && empty($this->_options['upgrade']) && empty($this->_options['force'])) { + $this->log(0, "Package '{$curinfo['package']}' already installed, skipping"); + return false; + } + if (in_array($pkgfile, $this->_toDownload)) { + return false; + } + $releases = $this->_remote->call('package.info', $pkgfile, 'releases', true); + if (!count($releases)) { + return $this->raiseError("No releases found for package '$pkgfile'"); + } + // Want a specific version/state + if ($version !== null) { + // Passed Foo-1.2 + if ($this->validPackageVersion($version)) { + if (!isset($releases[$version])) { + return $this->raiseError("No release with version '$version' found for '$pkgfile'"); + } + // Passed Foo-alpha + } elseif (in_array($version, $this->getReleaseStates())) { + $state = $version; + $version = 0; + foreach ($releases as $ver => $inf) { + if ($inf['state'] == $state && version_compare("$version", "$ver") < 0) { + $version = $ver; + break; + } + } + if ($version == 0) { + return $this->raiseError("No release with state '$state' found for '$pkgfile'"); + } + // invalid postfix passed + } else { + return $this->raiseError("Invalid postfix '-$version', be sure to pass a valid PEAR ". + "version number or release state"); + } + // Guess what to download + } else { + $states = $this->betterStates($this->_preferredState, true); + $possible = false; + $version = 0; + foreach ($releases as $ver => $inf) { + if (in_array($inf['state'], $states) && version_compare("$version", "$ver") < 0) { + $version = $ver; + break; + } + } + if ($version === 0 && !isset($this->_options['force'])) { + return $this->raiseError('No release with state equal to: \'' . implode(', ', $states) . + "' found for '$pkgfile'"); + } elseif ($version === 0) { + $this->log(0, "Warning: $pkgfile is state '$inf[state]' which is less stable " . + "than state '$this->_preferredState'"); + } + } + // Check if we haven't already the version + if (empty($this->_options['force']) && !is_null($curinfo)) { + if ($curinfo['version'] == $version) { + $this->log(0, "Package '{$curinfo['package']}-{$curinfo['version']}' already installed, skipping"); + return false; + } elseif (version_compare("$version", "{$curinfo['version']}") < 0) { + $this->log(0, "Package '{$curinfo['package']}' version '{$curinfo['version']}' " . + " is installed and {$curinfo['version']} is > requested '$version', skipping"); + return false; + } + } + $this->_toDownload[] = $pkgfile; + return $this->_downloadFile($pkgfile, $version, $origpkgfile, $state); + } + + // }}} + // {{{ _processDependency($package, $info, $mywillinstall) + + /** + * Process a dependency, download if necessary + * @param array dependency information from PEAR_Remote call + * @param array packages that will be installed in this iteration + * @return false|string|PEAR_Error + * @access private + * @todo Add test for relation 'lt'/'le' -> make sure that the dependency requested is + * in fact lower than the required value. This will be very important for BC dependencies + */ + function _processDependency($package, $info, $mywillinstall) + { + $state = $this->_preferredState; + if (!isset($this->_options['alldeps']) && isset($info['optional']) && + $info['optional'] == 'yes') { + // skip optional deps + $this->log(0, "skipping Package '$package' optional dependency '$info[name]'"); + return false; + } + // {{{ get releases + $releases = $this->_remote->call('package.info', $info['name'], 'releases', true); + if (PEAR::isError($releases)) { + return $releases; + } + if (!count($releases)) { + if (!isset($this->_installed[strtolower($info['name'])])) { + $this->pushError("Package '$package' dependency '$info[name]' ". + "has no releases"); + } + return false; + } + $found = false; + $save = $releases; + while(count($releases) && !$found) { + if (!empty($state) && $state != 'any') { + list($release_version, $release) = each($releases); + if ($state != $release['state'] && + !in_array($release['state'], $this->betterStates($state))) + { + // drop this release - it ain't stable enough + array_shift($releases); + } else { + $found = true; + } + } else { + $found = true; + } + } + if (!count($releases) && !$found) { + $get = array(); + foreach($save as $release) { + $get = array_merge($get, + $this->betterStates($release['state'], true)); + } + $savestate = array_shift($get); + $this->pushError( "Release for '$package' dependency '$info[name]' " . + "has state '$savestate', requires '$state'"); + return false; + } + if (in_array(strtolower($info['name']), $this->_toDownload) || + isset($mywillinstall[strtolower($info['name'])])) { + // skip upgrade check for packages we will install + return false; + } + if (!isset($this->_installed[strtolower($info['name'])])) { + // check to see if we can install the specific version required + if ($info['rel'] == 'eq') { + return $info['name'] . '-' . $info['version']; + } + // skip upgrade check for packages we don't have installed + return $info['name']; + } + // }}} + + // {{{ see if a dependency must be upgraded + $inst_version = $this->_registry->packageInfo($info['name'], 'version'); + if (!isset($info['version'])) { + // this is a rel='has' dependency, check against latest + if (version_compare($release_version, $inst_version, 'le')) { + return false; + } else { + return $info['name']; + } + } + if (version_compare($info['version'], $inst_version, 'le')) { + // installed version is up-to-date + return false; + } + return $info['name']; + } + + // }}} + // {{{ _downloadCallback() + + function _downloadCallback($msg, $params = null) + { + switch ($msg) { + case 'saveas': + $this->log(1, "downloading $params ..."); + break; + case 'done': + $this->log(1, '...done: ' . number_format($params, 0, '', ',') . ' bytes'); + break; + case 'bytesread': + static $bytes; + if (empty($bytes)) { + $bytes = 0; + } + if (!($bytes % 10240)) { + $this->log(1, '.', false); + } + $bytes += $params; + break; + case 'start': + $this->log(1, "Starting to download {$params[0]} (".number_format($params[1], 0, '', ',')." bytes)"); + break; + } + if (method_exists($this->ui, '_downloadCallback')) + $this->ui->_downloadCallback($msg, $params); + } + + // }}} + // {{{ _prependPath($path, $prepend) + + function _prependPath($path, $prepend) + { + if (strlen($prepend) > 0) { + if (OS_WINDOWS && preg_match('/^[a-z]:/i', $path)) { + $path = $prepend . substr($path, 2); + } else { + $path = $prepend . $path; + } + } + return $path; + } + // }}} + // {{{ pushError($errmsg, $code) + + /** + * @param string + * @param integer + */ + function pushError($errmsg, $code = -1) + { + array_push($this->_errorStack, array($errmsg, $code)); + } + + // }}} + // {{{ getErrorMsgs() + + function getErrorMsgs() + { + $msgs = array(); + $errs = $this->_errorStack; + foreach ($errs as $err) { + $msgs[] = $err[0]; + } + $this->_errorStack = array(); + return $msgs; + } + + // }}} +} +// }}} + +?> diff --git a/common/PEAR/PEAR/ErrorStack.php b/common/PEAR/PEAR/ErrorStack.php new file mode 100644 index 0000000..cf0ad99 --- /dev/null +++ b/common/PEAR/PEAR/ErrorStack.php @@ -0,0 +1,970 @@ + | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: ErrorStack.php,v 1.1.2.2 2004/06/12 05:50:51 cellog Exp $ + +/** + * Error Stack Implementation + * + * This is an incredibly simple implementation of a very complex error handling + * facility. It contains the ability + * to track multiple errors from multiple packages simultaneously. In addition, + * it can track errors of many levels, save data along with the error, context + * information such as the exact file, line number, class and function that + * generated the error, and if necessary, it can raise a traditional PEAR_Error. + * It has built-in support for PEAR::Log, to log errors as they occur + * + * Since version 0.2alpha, it is also possible to selectively ignore errors, + * through the use of an error callback, see {@link pushCallback()} + * + * Since version 0.3alpha, it is possible to specify the exception class + * returned from {@link push()} + * @author Greg Beaver + * @version 0.6alpha + * @package PEAR_ErrorStack + * @category Debugging + * @license http://www.php.net/license/3_0.txt PHP License v3.0 + */ + +/** + * Singleton storage + * + * Format: + *
+ * array(
+ *  'package1' => PEAR_ErrorStack object,
+ *  'package2' => PEAR_ErrorStack object,
+ *  ...
+ * )
+ * 
+ * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] + */ +$GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] = array(); + +/** + * Global error callback (default) + * + * This is only used if set to non-false. * is the default callback for + * all packages, whereas specific packages may set a default callback + * for all instances, regardless of whether they are a singleton or not. + * + * To exclude non-singletons, only set the local callback for the singleton + * @see PEAR_ErrorStack::setDefaultCallback() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] + */ +$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'] = array( + '*' => false, +); + +/** + * Global Log object (default) + * + * This is only used if set to non-false. Use to set a default log object for + * all stacks, regardless of instantiation order or location + * @see PEAR_ErrorStack::setDefaultLogger() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] + */ +$GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = false; + +/** + * Global Overriding Callback + * + * This callback will override any error callbacks that specific loggers have set. + * Use with EXTREME caution + * @see PEAR_ErrorStack::staticPushCallback() + * @access private + * @global array $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] + */ +$GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); + +/**#@+ + * One of four possible return values from the error Callback + * @see PEAR_ErrorStack::_errorCallback() + */ +/** + * If this is returned, then the error will be both pushed onto the stack + * and logged. + */ +define('PEAR_ERRORSTACK_PUSHANDLOG', 1); +/** + * If this is returned, then the error will only be pushed onto the stack, + * and not logged. + */ +define('PEAR_ERRORSTACK_PUSH', 2); +/** + * If this is returned, then the error will only be logged, but not pushed + * onto the error stack. + */ +define('PEAR_ERRORSTACK_LOG', 3); +/** + * If this is returned, then the error is completely ignored. + */ +define('PEAR_ERRORSTACK_IGNORE', 4); +/**#@-*/ + +/** + * Error code for an attempt to instantiate a non-class as a PEAR_ErrorStack in + * the singleton method. + */ +define('PEAR_ERRORSTACK_ERR_NONCLASS', 1); + +/** + * Error code for an attempt to pass an object into {@link PEAR_ErrorStack::getMessage()} + * that has no __toString() method + */ +define('PEAR_ERRORSTACK_ERR_OBJTOSTRING', 2); +/** + * Error Stack Implementation + * + * Usage: + * + * // global error stack + * $global_stack = &PEAR_ErrorStack::singleton('MyPackage'); + * // local error stack + * $local_stack = new PEAR_ErrorStack('MyPackage'); + * + * @copyright 2004 Gregory Beaver + * @package PEAR_ErrorStack + * @license http://www.php.net/license/3_0.txt PHP License + */ +class PEAR_ErrorStack { + /** + * Errors are stored in the order that they are pushed on the stack. + * @since 0.4alpha Errors are no longer organized by error level. + * This renders pop() nearly unusable, and levels could be more easily + * handled in a callback anyway + * @var array + * @access private + */ + var $_errors = array(); + + /** + * Storage of errors by level. + * + * Allows easy retrieval and deletion of only errors from a particular level + * @since PEAR 1.4.0dev + * @var array + * @access private + */ + var $_errorsByLevel = array(); + + /** + * Package name this error stack represents + * @var string + * @access protected + */ + var $_package; + + /** + * Determines whether a PEAR_Error is thrown upon every error addition + * @var boolean + * @access private + */ + var $_compat = false; + + /** + * If set to a valid callback, this will be used to generate the error + * message from the error code, otherwise the message passed in will be + * used + * @var false|string|array + * @access private + */ + var $_msgCallback = false; + + /** + * If set to a valid callback, this will be used to generate the error + * context for an error. For PHP-related errors, this will be a file + * and line number as retrieved from debug_backtrace(), but can be + * customized for other purposes. The error might actually be in a separate + * configuration file, or in a database query. + * @var false|string|array + * @access protected + */ + var $_contextCallback = false; + + /** + * If set to a valid callback, this will be called every time an error + * is pushed onto the stack. The return value will be used to determine + * whether to allow an error to be pushed or logged. + * + * The return value must be one an PEAR_ERRORSTACK_* constant + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @var false|string|array + * @access protected + */ + var $_errorCallback = array(); + + /** + * PEAR::Log object for logging errors + * @var false|Log + * @access protected + */ + var $_logger = false; + + /** + * Class name to use for a PHP 5 exception that will be returned + * @var string + * @access protected + */ + var $_exceptionClass = 'Exception'; + + /** + * Error messages - designed to be overridden + * @var array + * @abstract + */ + var $_errorMsgs = array(); + + /** + * Set up a new error stack + * + * @param string $package name of the package this error stack represents + * @param callback $msgCallback callback used for error message generation + * @param callback $contextCallback callback used for context generation, + * defaults to {@link getFileLine()} + * @param boolean $throwPEAR_Error + * @param string $exceptionClass exception class to instantiate if + * in PHP 5 + */ + function PEAR_ErrorStack($package, $msgCallback = false, $contextCallback = false, + $throwPEAR_Error = false, $exceptionClass = null) + { + $this->_package = $package; + $this->setMessageCallback($msgCallback); + $this->setContextCallback($contextCallback); + $this->_compat = $throwPEAR_Error; + // this allows child classes to simply redefine $this->_exceptionClass + if (!is_null($exceptionClass)) { + $this->_exceptionClass = $exceptionClass; + } + } + + /** + * Return a single error stack for this package. + * + * Note that all parameters are ignored if the stack for package $package + * has already been instantiated + * @param string $package name of the package this error stack represents + * @param callback $msgCallback callback used for error message generation + * @param callback $contextCallback callback used for context generation, + * defaults to {@link getFileLine()} + * @param boolean $throwPEAR_Error + * @param string $exceptionClass exception class to instantiate if + * in PHP 5 + * @param string $stackClass class to instantiate + * @static + * @return PEAR_ErrorStack + */ + function &singleton($package, $msgCallback = false, $contextCallback = false, + $throwPEAR_Error = false, $exceptionClass = null, + $stackClass = 'PEAR_ErrorStack') + { + if (isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]; + } + if (!class_exists($stackClass)) { + $trace = debug_backtrace(); + PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_NONCLASS, + 'exception', array('stackclass' => $stackClass), + 'stack class "%stackclass%" is not a valid class name (should be like PEAR_ErrorStack)', + false, $trace); + } + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package] = + &new $stackClass($package, $msgCallback, $contextCallback, $throwPEAR_Error, + $exceptionClass); + } + + /** + * Internal error handler for PEAR_ErrorStack class + * + * Dies if the error is an exception (and would have died anyway) + * @access private + */ + function _handleError($err) + { + if ($err['level'] == 'exception') { + $message = $err['message']; + if (isset($_SERVER['REQUEST_URI'])) { + echo '
'; + } else { + echo "\n"; + } + var_dump($err['context']); + die($message); + } + } + + /** + * Set up a PEAR::Log object for all error stacks that don't have one + * @param Log $log + * @static + */ + function setDefaultLogger(&$log) + { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER'] = &$log; + } + + /** + * Set up a PEAR::Log object for this error stack + * @param Log $log + */ + function setLogger(&$log) + { + $this->_logger = &$log; + } + + /** + * Set an error code => error message mapping callback + * + * This method sets the callback that can be used to generate error + * messages for any instance + * @param array|string Callback function/method + */ + function setMessageCallback($msgCallback) + { + if (!$msgCallback) { + $this->_msgCallback = array(&$this, 'getErrorMessage'); + } else { + if (is_callable($msgCallback)) { + $this->_msgCallback = $msgCallback; + } + } + } + + /** + * Get an error code => error message mapping callback + * + * This method returns the current callback that can be used to generate error + * messages + * @return array|string|false Callback function/method or false if none + */ + function getMessageCallback() + { + return $this->_msgCallback; + } + + /** + * Sets a default callback to be used by all error stacks + * + * This method sets the callback that can be used to generate error + * messages for a singleton + * @param array|string Callback function/method + * @param string Package name, or false for all packages + * @static + */ + function setDefaultCallback($callback = false, $package = false) + { + if (!is_callable($callback)) { + $callback = false; + } + $package = $package ? $package : '*'; + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$package] = $callback; + } + + /** + * Set an error code => error message mapping callback + * + * This method sets the callback that can be used to generate error + * messages for any PEAR_ErrorStack instance + * @param array|string Callback function/method + */ + function setContextCallback($contextCallback) + { + if (!$contextCallback) { + $this->_contextCallback = array(&$this, 'getFileLine'); + } else { + if (is_callable($contextCallback)) { + $this->_contextCallback = $contextCallback; + } + } + } + + /** + * Set an error Callback + * If set to a valid callback, this will be called every time an error + * is pushed onto the stack. The return value will be used to determine + * whether to allow an error to be pushed or logged. + * + * The return value must be one of the ERRORSTACK_* constants. + * + * This functionality can be used to emulate PEAR's pushErrorHandling, and + * the PEAR_ERROR_CALLBACK mode, without affecting the integrity of + * the error stack or logging + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @see popCallback() + * @param string|array $cb + */ + function pushCallback($cb) + { + array_push($this->_errorCallback, $cb); + } + + /** + * Remove a callback from the error callback stack + * @see pushCallback() + * @return array|string|false + */ + function popCallback() + { + if (!count($this->_errorCallback)) { + return false; + } + return array_pop($this->_errorCallback); + } + + /** + * Set a temporary overriding error callback for every package error stack + * + * Use this to temporarily disable all existing callbacks (can be used + * to emulate the @ operator, for instance) + * @see PEAR_ERRORSTACK_PUSHANDLOG, PEAR_ERRORSTACK_PUSH, PEAR_ERRORSTACK_LOG + * @see staticPopCallback(), pushCallback() + * @param string|array $cb + * @static + */ + function staticPushCallback($cb) + { + array_push($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'], $cb); + } + + /** + * Remove a temporary overriding error callback + * @see staticPushCallback() + * @return array|string|false + * @static + */ + function staticPopCallback() + { + array_pop($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK']); + if (!is_array($GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'])) { + $GLOBALS['_PEAR_ERRORSTACK_OVERRIDE_CALLBACK'] = array(); + } + } + + /** + * Add an error to the stack + * + * If the message generator exists, it is called with 2 parameters. + * - the current Error Stack object + * - an array that is in the same format as an error. Available indices + * are 'code', 'package', 'time', 'params', 'level', and 'context' + * + * Next, if the error should contain context information, this is + * handled by the context grabbing method. + * Finally, the error is pushed onto the proper error stack + * @param int $code Package-specific error code + * @param string $level Error level. This is NOT spell-checked + * @param array $params associative array of error parameters + * @param string $msg Error message, or a portion of it if the message + * is to be generated + * @param array $repackage If this error re-packages an error pushed by + * another package, place the array returned from + * {@link pop()} in this parameter + * @param array $backtrace Protected parameter: use this to pass in the + * {@link debug_backtrace()} that should be used + * to find error context + * @return PEAR_Error|array|Exception + * if compatibility mode is on, a PEAR_Error is also + * thrown. If the class Exception exists, then one + * is returned to allow code like: + * + * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob'))); + * + * + * The errorData property of the exception class will be set to the array + * that would normally be returned. If a PEAR_Error is returned, the userinfo + * property is set to the array + * + * Otherwise, an array is returned in this format: + * + * array( + * 'code' => $code, + * 'params' => $params, + * 'package' => $this->_package, + * 'level' => $level, + * 'time' => time(), + * 'context' => $context, + * 'message' => $msg, + * //['repackage' => $err] repackaged error array + * ); + * + */ + function push($code, $level = 'error', $params = array(), $msg = false, + $repackage = false, $backtrace = false) + { + $context = false; + // grab error context + if ($this->_contextCallback) { + if (!$backtrace) { + $backtrace = debug_backtrace(); + } + $context = call_user_func($this->_contextCallback, $code, $params, $backtrace); + } + + // save error + $time = explode(' ', microtime()); + $time = $time[1] + $time[0]; + $err = array( + 'code' => $code, + 'params' => $params, + 'package' => $this->_package, + 'level' => $level, + 'time' => $time, + 'context' => $context, + 'message' => $msg, + ); + + // set up the error message, if necessary + if ($this->_msgCallback) { + $msg = call_user_func_array($this->_msgCallback, + array(&$this, $err)); + $err['message'] = $msg; + } + + + if ($repackage) { + $err['repackage'] = $repackage; + } + $push = $log = true; + // try the overriding callback first + $callback = $this->staticPopCallback(); + if ($callback) { + $this->staticPushCallback($callback); + } + if (!is_callable($callback)) { + // try the local callback next + $callback = $this->popCallback(); + if (is_callable($callback)) { + $this->pushCallback($callback); + } else { + // try the default callback + $callback = isset($GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package]) ? + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK'][$this->_package] : + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_CALLBACK']['*']; + } + } + if (is_callable($callback)) { + switch(call_user_func($callback, $err)){ + case PEAR_ERRORSTACK_IGNORE: + return $err; + break; + case PEAR_ERRORSTACK_PUSH: + $log = false; + break; + case PEAR_ERRORSTACK_LOG: + $push = false; + break; + // anything else returned has the same effect as pushandlog + } + } + if ($push) { + array_unshift($this->_errors, $err); + $this->_errorsByLevel[$err['level']][] = &$this->_errors[0]; + } + if ($log) { + if ($this->_logger || $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']) { + $this->_log($err); + } + } + if ($this->_compat && $push) { + return $this->raiseError($msg, $code, null, null, $err); + } + if (class_exists($this->_exceptionClass)) { + $exception = $this->_exceptionClass; + if (is_string($msg) && is_numeric($code)) { + $code = $code + 0; + } + $ret = new $exception($msg, $code); + $ret->errorData = $err; + return $ret; + } + return $err; + } + + /** + * Static version of {@link push()} + * + * @param string $package Package name this error belongs to + * @param int $code Package-specific error code + * @param string $level Error level. This is NOT spell-checked + * @param array $params associative array of error parameters + * @param string $msg Error message, or a portion of it if the message + * is to be generated + * @param array $repackage If this error re-packages an error pushed by + * another package, place the array returned from + * {@link pop()} in this parameter + * @param array $backtrace Protected parameter: use this to pass in the + * {@link debug_backtrace()} that should be used + * to find error context + * @return PEAR_Error|null|Exception + * if compatibility mode is on, a PEAR_Error is also + * thrown. If the class Exception exists, then one + * is returned to allow code like: + * + * throw ($stack->push(MY_ERROR_CODE, 'error', array('username' => 'grob'))); + * + * @static + */ + function staticPush($package, $code, $level = 'error', $params = array(), + $msg = false, $repackage = false, $backtrace = false) + { + $s = &PEAR_ErrorStack::singleton($package); + if ($s->_contextCallback) { + if (!$backtrace) { + $backtrace = debug_backtrace(); + } + } + return $s->push($code, $level, $params, $msg, $repackage, $backtrace); + } + + /** + * Log an error using PEAR::Log + * @param array $err Error array + * @param array $levels Error level => Log constant map + * @access protected + */ + function _log($err, $levels = array( + 'exception' => PEAR_LOG_CRIT, + 'alert' => PEAR_LOG_ALERT, + 'critical' => PEAR_LOG_CRIT, + 'error' => PEAR_LOG_ERR, + 'warning' => PEAR_LOG_WARNING, + 'notice' => PEAR_LOG_NOTICE, + 'info' => PEAR_LOG_INFO, + 'debug' => PEAR_LOG_DEBUG)) + { + if (isset($levels[$err['level']])) { + $level = $levels[$err['level']]; + } else { + $level = PEAR_LOG_INFO; + } + if ($this->_logger) { + $this->_logger->log($err['message'], $level, $err); + } else { + $GLOBALS['_PEAR_ERRORSTACK_DEFAULT_LOGGER']->log($err['message'], $level, $err); + } + } + + + /** + * Pop an error off of the error stack + * + * @return false|array + * @since 0.4alpha it is no longer possible to specify a specific error + * level to return - the last error pushed will be returned, instead + */ + function pop() + { + return @array_shift($this->_errors); + } + + /** + * Determine whether there are any errors on the stack + * @param string|array Level name. Use to determine if any errors + * of level (string), or levels (array) have been pushed + * @return boolean + */ + function hasErrors($level = false) + { + if ($level) { + return isset($this->_errorsByLevel[$level]); + } + return count($this->_errors); + } + + /** + * Retrieve all errors since last purge + * + * @param boolean set in order to empty the error stack + * @param string level name, to return only errors of a particular severity + * @return array + */ + function getErrors($purge = false, $level = false) + { + if (!$purge) { + if ($level) { + if (!isset($this->_errorsByLevel[$level])) { + return array(); + } else { + return $this->_errorsByLevel[$level]; + } + } else { + return $this->_errors; + } + } + if ($level) { + $ret = $this->_errorsByLevel[$level]; + foreach ($this->_errorsByLevel[$level] as $i => $unused) { + // entries are references to the $_errors array + $this->_errorsByLevel[$level][$i] = false; + } + // array_filter removes all entries === false + $this->_errors = array_filter($this->_errors); + unset($this->_errorsByLevel[$level]); + return $ret; + } + $ret = $this->_errors; + $this->_errors = array(); + $this->_errorsByLevel = array(); + return $ret; + } + + /** + * Determine whether there are any errors on a single error stack, or on any error stack + * + * The optional parameter can be used to test the existence of any errors without the need of + * singleton instantiation + * @param string|false Package name to check for errors + * @param string Level name to check for a particular severity + * @return boolean + * @static + */ + function staticHasErrors($package = false, $level = false) + { + if ($package) { + if (!isset($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package])) { + return false; + } + return $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->hasErrors($level); + } + foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { + if ($obj->hasErrors($level)) { + return true; + } + } + return false; + } + + /** + * Get a list of all errors since last purge, organized by package + * @since PEAR 1.4.0dev BC break! $level is now in the place $merge used to be + * @param boolean $clearStack Set to purge the error stack of existing errors + * @param string $level Set to a level name in order to retrieve only errors of a particular level + * @param boolean $merge Set to return a flat array, not organized by package + * @param array $sortfunc Function used to sort a merged array - default + * sorts by time, and should be good for most cases + * @static + * @return array + */ + function staticGetErrors($purge = false, $level = false, $merge = false, $sortfunc = array('PEAR_ErrorStack', '_sortErrors')) + { + $ret = array(); + if (!is_callable($sortfunc)) { + $sortfunc = array('PEAR_ErrorStack', '_sortErrors'); + } + foreach ($GLOBALS['_PEAR_ERRORSTACK_SINGLETON'] as $package => $obj) { + $test = $GLOBALS['_PEAR_ERRORSTACK_SINGLETON'][$package]->getErrors($purge, $level); + if ($test) { + if ($merge) { + $ret = array_merge($ret, $test); + } else { + $ret[$package] = $test; + } + } + } + if ($merge) { + usort($ret, $sortfunc); + } + return $ret; + } + + /** + * Error sorting function, sorts by time + * @access private + */ + function _sortErrors($a, $b) + { + if ($a['time'] == $b['time']) { + return 0; + } + if ($a['time'] < $b['time']) { + return 1; + } + return -1; + } + + /** + * Standard file/line number/function/class context callback + * + * This function uses a backtrace generated from {@link debug_backtrace()} + * and so will not work at all in PHP < 4.3.0. The frame should + * reference the frame that contains the source of the error. + * @return array|false either array('file' => file, 'line' => line, + * 'function' => function name, 'class' => class name) or + * if this doesn't work, then false + * @param unused + * @param integer backtrace frame. + * @param array Results of debug_backtrace() + * @static + */ + function getFileLine($code, $params, $backtrace = null) + { + if ($backtrace === null) { + return false; + } + $frame = 0; + $functionframe = 1; + if (!isset($backtrace[1])) { + $functionframe = 0; + } else { + while (isset($backtrace[$functionframe]['function']) && + $backtrace[$functionframe]['function'] == 'eval' && + isset($backtrace[$functionframe + 1])) { + $functionframe++; + } + } + if (isset($backtrace[$frame])) { + if (!isset($backtrace[$frame]['file'])) { + $frame++; + } + $funcbacktrace = $backtrace[$functionframe]; + $filebacktrace = $backtrace[$frame]; + $ret = array('file' => $filebacktrace['file'], + 'line' => $filebacktrace['line']); + // rearrange for eval'd code or create function errors + if (strpos($filebacktrace['file'], '(') && + preg_match(';^(.*?)\((\d+)\) : (.*?)$;', $filebacktrace['file'], + $matches)) { + $ret['file'] = $matches[1]; + $ret['line'] = $matches[2] + 0; + } + if (isset($funcbacktrace['function']) && isset($backtrace[1])) { + if ($funcbacktrace['function'] != 'eval') { + if ($funcbacktrace['function'] == '__lambda_func') { + $ret['function'] = 'create_function() code'; + } else { + $ret['function'] = $funcbacktrace['function']; + } + } + } + if (isset($funcbacktrace['class']) && isset($backtrace[1])) { + $ret['class'] = $funcbacktrace['class']; + } + return $ret; + } + return false; + } + + /** + * Standard error message generation callback + * + * This method may also be called by a custom error message generator + * to fill in template values from the params array, simply + * set the third parameter to the error message template string to use + * + * The special variable %__msg% is reserved: use it only to specify + * where a message passed in by the user should be placed in the template, + * like so: + * + * Error message: %msg% - internal error + * + * If the message passed like so: + * + * + * $stack->push(ERROR_CODE, 'error', array(), 'server error 500'); + * + * + * The returned error message will be "Error message: server error 500 - + * internal error" + * @param PEAR_ErrorStack + * @param array + * @param string|false Pre-generated error message template + * @static + * @return string + */ + function getErrorMessage(&$stack, $err, $template = false) + { + if ($template) { + $mainmsg = $template; + } else { + $mainmsg = $stack->getErrorMessageTemplate($err['code']); + } + $mainmsg = str_replace('%__msg%', $err['message'], $mainmsg); + if (count($err['params'])) { + foreach ($err['params'] as $name => $val) { + if (is_array($val)) { + // @ is needed in case $val is a multi-dimensional array + $val = @implode(', ', $val); + } + if (is_object($val)) { + if (method_exists($val, '__toString')) { + $val = $val->__toString(); + } else { + PEAR_ErrorStack::staticPush('PEAR_ErrorStack', PEAR_ERRORSTACK_ERR_OBJTOSTRING, + 'warning', array('obj' => get_class($val)), + 'object %obj% passed into getErrorMessage, but has no __toString() method'); + $val = 'Object'; + } + } + $mainmsg = str_replace('%' . $name . '%', $val, $mainmsg); + } + } + return $mainmsg; + } + + /** + * Standard Error Message Template generator from code + * @return string + */ + function getErrorMessageTemplate($code) + { + if (!isset($this->_errorMsgs[$code])) { + return '%__msg%'; + } + return $this->_errorMsgs[$code]; + } + + /** + * Set the Error Message Template array + * + * The array format must be: + *
+     * array(error code => 'message template',...)
+     * 
+ * + * Error message parameters passed into {@link push()} will be used as input + * for the error message. If the template is 'message %foo% was %bar%', and the + * parameters are array('foo' => 'one', 'bar' => 'six'), the error message returned will + * be 'message one was six' + * @return string + */ + function setErrorMessageTemplate($template) + { + $this->_errorMsgs = $template; + } + + + /** + * emulate PEAR::raiseError() + * + * @return PEAR_Error + */ + function raiseError() + { + require_once 'PEAR.php'; + $args = func_get_args(); + return call_user_func_array(array('PEAR', 'raiseError'), $args); + } +} +$stack = &PEAR_ErrorStack::singleton('PEAR_ErrorStack'); +$stack->pushCallback(array('PEAR_ErrorStack', '_handleError')); +?> diff --git a/common/PEAR/PEAR/Frontend/CLI.php b/common/PEAR/PEAR/Frontend/CLI.php new file mode 100644 index 0000000..5070c25 --- /dev/null +++ b/common/PEAR/PEAR/Frontend/CLI.php @@ -0,0 +1,504 @@ + | + +----------------------------------------------------------------------+ + + $Id: CLI.php,v 1.25.2.15 2004/01/26 01:26:47 pajoye Exp $ +*/ + +require_once "PEAR.php"; + +class PEAR_Frontend_CLI extends PEAR +{ + // {{{ properties + + /** + * What type of user interface this frontend is for. + * @var string + * @access public + */ + var $type = 'CLI'; + var $lp = ''; // line prefix + + var $params = array(); + var $term = array( + 'bold' => '', + 'normal' => '', + ); + + // }}} + + // {{{ constructor + + function PEAR_Frontend_CLI() + { + parent::PEAR(); + $term = getenv('TERM'); //(cox) $_ENV is empty for me in 4.1.1 + if ($term) { + // XXX can use ncurses extension here, if available + if (preg_match('/^(xterm|vt220|linux)/', $term)) { + $this->term['bold'] = sprintf("%c%c%c%c", 27, 91, 49, 109); + $this->term['normal']=sprintf("%c%c%c", 27, 91, 109); + } elseif (preg_match('/^vt100/', $term)) { + $this->term['bold'] = sprintf("%c%c%c%c%c%c", 27, 91, 49, 109, 0, 0); + $this->term['normal']=sprintf("%c%c%c%c%c", 27, 91, 109, 0, 0); + } + } elseif (OS_WINDOWS) { + // XXX add ANSI codes here + } + } + + // }}} + + // {{{ displayLine(text) + + function displayLine($text) + { + trigger_error("PEAR_Frontend_CLI::displayLine deprecated", E_USER_ERROR); + } + + function _displayLine($text) + { + print "$this->lp$text\n"; + } + + // }}} + // {{{ display(text) + + function display($text) + { + trigger_error("PEAR_Frontend_CLI::display deprecated", E_USER_ERROR); + } + + function _display($text) + { + print $text; + } + + // }}} + // {{{ displayError(eobj) + + /** + * @param object PEAR_Error object + */ + function displayError($eobj) + { + return $this->_displayLine($eobj->getMessage()); + } + + // }}} + // {{{ displayFatalError(eobj) + + /** + * @param object PEAR_Error object + */ + function displayFatalError($eobj) + { + $this->displayError($eobj); + exit(1); + } + + // }}} + // {{{ displayHeading(title) + + function displayHeading($title) + { + trigger_error("PEAR_Frontend_CLI::displayHeading deprecated", E_USER_ERROR); + } + + function _displayHeading($title) + { + print $this->lp.$this->bold($title)."\n"; + print $this->lp.str_repeat("=", strlen($title))."\n"; + } + + // }}} + // {{{ userDialog(prompt, [type], [default]) + + function userDialog($command, $prompts, $types = array(), $defaults = array()) + { + $result = array(); + if (is_array($prompts)) { + $fp = fopen("php://stdin", "r"); + foreach ($prompts as $key => $prompt) { + $type = $types[$key]; + $default = @$defaults[$key]; + if ($type == 'password') { + system('stty -echo'); + } + print "$this->lp$prompt "; + if ($default) { + print "[$default] "; + } + print ": "; + $line = fgets($fp, 2048); + if ($type == 'password') { + system('stty echo'); + print "\n"; + } + if ($default && trim($line) == "") { + $result[$key] = $default; + } else { + $result[$key] = $line; + } + } + fclose($fp); + } + return $result; + } + + // }}} + // {{{ userConfirm(prompt, [default]) + + function userConfirm($prompt, $default = 'yes') + { + trigger_error("PEAR_Frontend_CLI::userConfirm not yet converted", E_USER_ERROR); + static $positives = array('y', 'yes', 'on', '1'); + static $negatives = array('n', 'no', 'off', '0'); + print "$this->lp$prompt [$default] : "; + $fp = fopen("php://stdin", "r"); + $line = fgets($fp, 2048); + fclose($fp); + $answer = strtolower(trim($line)); + if (empty($answer)) { + $answer = $default; + } + if (in_array($answer, $positives)) { + return true; + } + if (in_array($answer, $negatives)) { + return false; + } + if (in_array($default, $positives)) { + return true; + } + return false; + } + + // }}} + // {{{ startTable([params]) + + function startTable($params = array()) + { + trigger_error("PEAR_Frontend_CLI::startTable deprecated", E_USER_ERROR); + } + + function _startTable($params = array()) + { + $params['table_data'] = array(); + $params['widest'] = array(); // indexed by column + $params['highest'] = array(); // indexed by row + $params['ncols'] = 0; + $this->params = $params; + } + + // }}} + // {{{ tableRow(columns, [rowparams], [colparams]) + + function tableRow($columns, $rowparams = array(), $colparams = array()) + { + trigger_error("PEAR_Frontend_CLI::tableRow deprecated", E_USER_ERROR); + } + + function _tableRow($columns, $rowparams = array(), $colparams = array()) + { + $highest = 1; + for ($i = 0; $i < sizeof($columns); $i++) { + $col = &$columns[$i]; + if (isset($colparams[$i]) && !empty($colparams[$i]['wrap'])) { + $col = wordwrap($col, $colparams[$i]['wrap'], "\n", 1); + } + if (strpos($col, "\n") !== false) { + $multiline = explode("\n", $col); + $w = 0; + foreach ($multiline as $n => $line) { + if (strlen($line) > $w) { + $w = strlen($line); + } + } + $lines = sizeof($multiline); + } else { + $w = strlen($col); + } + if ($w > @$this->params['widest'][$i]) { + $this->params['widest'][$i] = $w; + } + $tmp = count_chars($columns[$i], 1); + // handle unix, mac and windows formats + $lines = (isset($tmp[10]) ? $tmp[10] : @$tmp[13]) + 1; + if ($lines > $highest) { + $highest = $lines; + } + } + if (sizeof($columns) > $this->params['ncols']) { + $this->params['ncols'] = sizeof($columns); + } + $new_row = array( + 'data' => $columns, + 'height' => $highest, + 'rowparams' => $rowparams, + 'colparams' => $colparams, + ); + $this->params['table_data'][] = $new_row; + } + + // }}} + // {{{ endTable() + + function endTable() + { + trigger_error("PEAR_Frontend_CLI::endTable deprecated", E_USER_ERROR); + } + + function _endTable() + { + extract($this->params); + if (!empty($caption)) { + $this->_displayHeading($caption); + } + if (count($table_data) == 0) { + return; + } + if (!isset($width)) { + $width = $widest; + } else { + for ($i = 0; $i < $ncols; $i++) { + if (!isset($width[$i])) { + $width[$i] = $widest[$i]; + } + } + } + $border = false; + if (empty($border)) { + $cellstart = ''; + $cellend = ' '; + $rowend = ''; + $padrowend = false; + $borderline = ''; + } else { + $cellstart = '| '; + $cellend = ' '; + $rowend = '|'; + $padrowend = true; + $borderline = '+'; + foreach ($width as $w) { + $borderline .= str_repeat('-', $w + strlen($cellstart) + strlen($cellend) - 1); + $borderline .= '+'; + } + } + if ($borderline) { + $this->_displayLine($borderline); + } + for ($i = 0; $i < sizeof($table_data); $i++) { + extract($table_data[$i]); + if (!is_array($rowparams)) { + $rowparams = array(); + } + if (!is_array($colparams)) { + $colparams = array(); + } + $rowlines = array(); + if ($height > 1) { + for ($c = 0; $c < sizeof($data); $c++) { + $rowlines[$c] = preg_split('/(\r?\n|\r)/', $data[$c]); + if (sizeof($rowlines[$c]) < $height) { + $rowlines[$c] = array_pad($rowlines[$c], $height, ''); + } + } + } else { + for ($c = 0; $c < sizeof($data); $c++) { + $rowlines[$c] = array($data[$c]); + } + } + for ($r = 0; $r < $height; $r++) { + $rowtext = ''; + for ($c = 0; $c < sizeof($data); $c++) { + if (isset($colparams[$c])) { + $attribs = array_merge($rowparams, $colparams); + } else { + $attribs = $rowparams; + } + $w = isset($width[$c]) ? $width[$c] : 0; + //$cell = $data[$c]; + $cell = $rowlines[$c][$r]; + $l = strlen($cell); + if ($l > $w) { + $cell = substr($cell, 0, $w); + } + if (isset($attribs['bold'])) { + $cell = $this->bold($cell); + } + if ($l < $w) { + // not using str_pad here because we may + // add bold escape characters to $cell + $cell .= str_repeat(' ', $w - $l); + } + + $rowtext .= $cellstart . $cell . $cellend; + } + $rowtext .= $rowend; + $this->_displayLine($rowtext); + } + } + if ($borderline) { + $this->_displayLine($borderline); + } + } + + // }}} + // {{{ outputData() + + function outputData($data, $command = '_default') + { + switch ($command) { + case 'install': + case 'upgrade': + case 'upgrade-all': + if (isset($data['release_warnings'])) { + $this->_displayLine(''); + $this->_startTable(array( + 'border' => false, + 'caption' => 'Release Warnings' + )); + $this->_tableRow(array($data['release_warnings']), null, array(1 => array('wrap' => 55))); + $this->_endTable(); + $this->_displayLine(''); + } + $this->_displayLine($data['data']); + break; + case 'search': + $this->_startTable($data); + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); + } + + foreach($data['data'] as $category) { + foreach($category as $pkg) { + $this->_tableRow($pkg, null, array(1 => array('wrap' => 55))); + } + }; + $this->_endTable(); + break; + case 'list-all': + $this->_startTable($data); + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], array('bold' => true), array(1 => array('wrap' => 55))); + } + + foreach($data['data'] as $category) { + foreach($category as $pkg) { + unset($pkg[3]); + unset($pkg[4]); + $this->_tableRow($pkg, null, array(1 => array('wrap' => 55))); + } + }; + $this->_endTable(); + break; + case 'config-show': + $data['border'] = false; + $opts = array(0 => array('wrap' => 30), + 1 => array('wrap' => 20), + 2 => array('wrap' => 35)); + $this->_startTable($data); + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], + array('bold' => true), + $opts); + } + foreach($data['data'] as $group) { + foreach($group as $value) { + if ($value[2] == '') { + $value[2] = ""; + } + $this->_tableRow($value, null, $opts); + } + } + $this->_endTable(); + break; + case 'remote-info': + $data = array( + 'caption' => 'Package details:', + 'border' => false, + 'data' => array( + array("Latest", $data['stable']), + array("Installed", $data['installed']), + array("Package", $data['name']), + array("License", $data['license']), + array("Category", $data['category']), + array("Summary", $data['summary']), + array("Description", $data['description']), + ), + ); + default: { + if (is_array($data)) { + $this->_startTable($data); + $count = count($data['data'][0]); + if ($count == 2) { + $opts = array(0 => array('wrap' => 25), + 1 => array('wrap' => 48) + ); + } elseif ($count == 3) { + $opts = array(0 => array('wrap' => 30), + 1 => array('wrap' => 20), + 2 => array('wrap' => 35) + ); + } else { + $opts = null; + } + if (isset($data['headline']) && is_array($data['headline'])) { + $this->_tableRow($data['headline'], + array('bold' => true), + $opts); + } + foreach($data['data'] as $row) { + $this->_tableRow($row, null, $opts); + } + $this->_endTable(); + } else { + $this->_displayLine($data); + } + } + } + } + + // }}} + // {{{ log(text) + + + function log($text, $append_crlf = true) + { + if ($append_crlf) { + return $this->_displayLine($text); + } + return $this->_display($text); + } + + + // }}} + // {{{ bold($text) + + function bold($text) + { + if (empty($this->term['bold'])) { + return strtoupper($text); + } + return $this->term['bold'] . $text . $this->term['normal']; + } + + // }}} +} + +?> diff --git a/common/PEAR/PEAR/Installer.php b/common/PEAR/PEAR/Installer.php new file mode 100644 index 0000000..98ca899 --- /dev/null +++ b/common/PEAR/PEAR/Installer.php @@ -0,0 +1,1046 @@ + | +// | Tomas V.V.Cox | +// | Martin Jansen | +// +----------------------------------------------------------------------+ +// +// $Id: Installer.php,v 1.81.2.26 2004/06/12 05:50:51 cellog Exp $ + +require_once 'PEAR/Downloader.php'; + +/** + * Administration class used to install PEAR packages and maintain the + * installed package database. + * + * TODO: + * - Check dependencies break on package uninstall (when no force given) + * - add a guessInstallDest() method with the code from _installFile() and + * use that method in Registry::_rebuildFileMap() & Command_Registry::doList(), + * others.. + * + * @since PHP 4.0.2 + * @author Stig Bakken + * @author Martin Jansen + * @author Greg Beaver + */ +class PEAR_Installer extends PEAR_Downloader +{ + // {{{ properties + + /** name of the package directory, for example Foo-1.0 + * @var string + */ + var $pkgdir; + + /** directory where PHP code files go + * @var string + */ + var $phpdir; + + /** directory where PHP extension files go + * @var string + */ + var $extdir; + + /** directory where documentation goes + * @var string + */ + var $docdir; + + /** installation root directory (ala PHP's INSTALL_ROOT or + * automake's DESTDIR + * @var string + */ + var $installroot = ''; + + /** debug level + * @var int + */ + var $debug = 1; + + /** temporary directory + * @var string + */ + var $tmpdir; + + /** PEAR_Registry object used by the installer + * @var object + */ + var $registry; + + /** List of file transactions queued for an install/upgrade/uninstall. + * + * Format: + * array( + * 0 => array("rename => array("from-file", "to-file")), + * 1 => array("delete" => array("file-to-delete")), + * ... + * ) + * + * @var array + */ + var $file_operations = array(); + + // }}} + + // {{{ constructor + + /** + * PEAR_Installer constructor. + * + * @param object $ui user interface object (instance of PEAR_Frontend_*) + * + * @access public + */ + function PEAR_Installer(&$ui) + { + parent::PEAR_Common(); + $this->setFrontendObject($ui); + $this->debug = $this->config->get('verbose'); + //$this->registry = &new PEAR_Registry($this->config->get('php_dir')); + } + + // }}} + + // {{{ _deletePackageFiles() + + /** + * Delete a package's installed files, does not remove empty directories. + * + * @param string $package package name + * + * @return bool TRUE on success, or a PEAR error on failure + * + * @access private + */ + function _deletePackageFiles($package) + { + if (!strlen($package)) { + return $this->raiseError("No package to uninstall given"); + } + $filelist = $this->registry->packageInfo($package, 'filelist'); + if ($filelist == null) { + return $this->raiseError("$package not installed"); + } + foreach ($filelist as $file => $props) { + if (empty($props['installed_as'])) { + continue; + } + $path = $this->_prependPath($props['installed_as'], $this->installroot); + $this->addFileOperation('delete', array($path)); + } + return true; + } + + // }}} + // {{{ _installFile() + + /** + * @param string filename + * @param array attributes from tag in package.xml + * @param string path to install the file in + * @param array options from command-line + * @access private + */ + function _installFile($file, $atts, $tmp_path, $options) + { + // {{{ return if this file is meant for another platform + static $os; + if (isset($atts['platform'])) { + if (empty($os)) { + include_once "OS/Guess.php"; + $os = new OS_Guess(); + } + if (!$os->matchSignature($atts['platform'])) { + $this->log(3, "skipped $file (meant for $atts[platform], we are ".$os->getSignature().")"); + return PEAR_INSTALLER_SKIPPED; + } + } + // }}} + + // {{{ assemble the destination paths + switch ($atts['role']) { + case 'doc': + case 'data': + case 'test': + $dest_dir = $this->config->get($atts['role'] . '_dir') . + DIRECTORY_SEPARATOR . $this->pkginfo['package']; + unset($atts['baseinstalldir']); + break; + case 'ext': + case 'php': + $dest_dir = $this->config->get($atts['role'] . '_dir'); + break; + case 'script': + $dest_dir = $this->config->get('bin_dir'); + break; + case 'src': + case 'extsrc': + $this->source_files++; + return; + default: + return $this->raiseError("Invalid role `$atts[role]' for file $file"); + } + $save_destdir = $dest_dir; + if (!empty($atts['baseinstalldir'])) { + $dest_dir .= DIRECTORY_SEPARATOR . $atts['baseinstalldir']; + } + if (dirname($file) != '.' && empty($atts['install-as'])) { + $dest_dir .= DIRECTORY_SEPARATOR . dirname($file); + } + if (empty($atts['install-as'])) { + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . basename($file); + } else { + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . $atts['install-as']; + } + $orig_file = $tmp_path . DIRECTORY_SEPARATOR . $file; + + // Clean up the DIRECTORY_SEPARATOR mess + $ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR; + list($dest_file, $orig_file) = preg_replace(array('!\\\\+!', '!/!', "!$ds2+!"), + DIRECTORY_SEPARATOR, + array($dest_file, $orig_file)); + $installed_as = $dest_file; + $final_dest_file = $this->_prependPath($dest_file, $this->installroot); + $dest_dir = dirname($final_dest_file); + $dest_file = $dest_dir . DIRECTORY_SEPARATOR . '.tmp' . basename($final_dest_file); + // }}} + + if (!@is_dir($dest_dir)) { + if (!$this->mkDirHier($dest_dir)) { + return $this->raiseError("failed to mkdir $dest_dir", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ mkdir $dest_dir"); + } + if (empty($atts['replacements'])) { + if (!file_exists($orig_file)) { + return $this->raiseError("file does not exist", + PEAR_INSTALLER_FAILED); + } + if (!@copy($orig_file, $dest_file)) { + return $this->raiseError("failed to write $dest_file", + PEAR_INSTALLER_FAILED); + } + $this->log(3, "+ cp $orig_file $dest_file"); + if (isset($atts['md5sum'])) { + $md5sum = md5_file($dest_file); + } + } else { + // {{{ file with replacements + if (!file_exists($orig_file)) { + return $this->raiseError("file does not exist", + PEAR_INSTALLER_FAILED); + } + $fp = fopen($orig_file, "r"); + $contents = fread($fp, filesize($orig_file)); + fclose($fp); + if (isset($atts['md5sum'])) { + $md5sum = md5($contents); + } + $subst_from = $subst_to = array(); + foreach ($atts['replacements'] as $a) { + $to = ''; + if ($a['type'] == 'php-const') { + if (preg_match('/^[a-z0-9_]+$/i', $a['to'])) { + eval("\$to = $a[to];"); + } else { + $this->log(0, "invalid php-const replacement: $a[to]"); + continue; + } + } elseif ($a['type'] == 'pear-config') { + $to = $this->config->get($a['to']); + if (is_null($to)) { + $this->log(0, "invalid pear-config replacement: $a[to]"); + continue; + } + } elseif ($a['type'] == 'package-info') { + if (isset($this->pkginfo[$a['to']]) && is_string($this->pkginfo[$a['to']])) { + $to = $this->pkginfo[$a['to']]; + } else { + $this->log(0, "invalid package-info replacement: $a[to]"); + continue; + } + } + if (!is_null($to)) { + $subst_from[] = $a['from']; + $subst_to[] = $to; + } + } + $this->log(3, "doing ".sizeof($subst_from)." substitution(s) for $final_dest_file"); + if (sizeof($subst_from)) { + $contents = str_replace($subst_from, $subst_to, $contents); + } + $wp = @fopen($dest_file, "wb"); + if (!is_resource($wp)) { + return $this->raiseError("failed to create $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + if (!fwrite($wp, $contents)) { + return $this->raiseError("failed writing to $dest_file: $php_errormsg", + PEAR_INSTALLER_FAILED); + } + fclose($wp); + // }}} + } + // {{{ check the md5 + if (isset($md5sum)) { + if (strtolower($md5sum) == strtolower($atts['md5sum'])) { + $this->log(2, "md5sum ok: $final_dest_file"); + } else { + if (empty($options['force'])) { + // delete the file + @unlink($dest_file); + return $this->raiseError("bad md5sum for file $final_dest_file", + PEAR_INSTALLER_FAILED); + } else { + $this->log(0, "warning : bad md5sum for file $final_dest_file"); + } + } + } + // }}} + // {{{ set file permissions + if (!OS_WINDOWS) { + if ($atts['role'] == 'script') { + $mode = 0777 & ~(int)octdec($this->config->get('umask')); + $this->log(3, "+ chmod +x $dest_file"); + } else { + $mode = 0666 & ~(int)octdec($this->config->get('umask')); + } + $this->addFileOperation("chmod", array($mode, $dest_file)); + if (!@chmod($dest_file, $mode)) { + $this->log(0, "failed to change mode of $dest_file"); + } + } + // }}} + $this->addFileOperation("rename", array($dest_file, $final_dest_file)); + // Store the full path where the file was installed for easy unistall + $this->addFileOperation("installed_as", array($file, $installed_as, + $save_destdir, dirname(substr($dest_file, strlen($save_destdir))))); + + //$this->log(2, "installed: $dest_file"); + return PEAR_INSTALLER_OK; + } + + // }}} + // {{{ addFileOperation() + + /** + * Add a file operation to the current file transaction. + * + * @see startFileTransaction() + * @var string $type This can be one of: + * - rename: rename a file ($data has 2 values) + * - chmod: change permissions on a file ($data has 2 values) + * - delete: delete a file ($data has 1 value) + * - rmdir: delete a directory if empty ($data has 1 value) + * - installed_as: mark a file as installed ($data has 4 values). + * @var array $data For all file operations, this array must contain the + * full path to the file or directory that is being operated on. For + * the rename command, the first parameter must be the file to rename, + * the second its new name. + * + * The installed_as operation contains 4 elements in this order: + * 1. Filename as listed in the filelist element from package.xml + * 2. Full path to the installed file + * 3. Full path from the php_dir configuration variable used in this + * installation + * 4. Relative path from the php_dir that this file is installed in + */ + function addFileOperation($type, $data) + { + if (!is_array($data)) { + return $this->raiseError('Internal Error: $data in addFileOperation' + . ' must be an array, was ' . gettype($data)); + } + if ($type == 'chmod') { + $octmode = decoct($data[0]); + $this->log(3, "adding to transaction: $type $octmode $data[1]"); + } else { + $this->log(3, "adding to transaction: $type " . implode(" ", $data)); + } + $this->file_operations[] = array($type, $data); + } + + // }}} + // {{{ startFileTransaction() + + function startFileTransaction($rollback_in_case = false) + { + if (count($this->file_operations) && $rollback_in_case) { + $this->rollbackFileTransaction(); + } + $this->file_operations = array(); + } + + // }}} + // {{{ commitFileTransaction() + + function commitFileTransaction() + { + $n = count($this->file_operations); + $this->log(2, "about to commit $n file operations"); + // {{{ first, check permissions and such manually + $errors = array(); + foreach ($this->file_operations as $tr) { + list($type, $data) = $tr; + switch ($type) { + case 'rename': + if (!file_exists($data[0])) { + $errors[] = "cannot rename file $data[0], doesn't exist"; + } + // check that dest dir. is writable + if (!is_writable(dirname($data[1]))) { + $errors[] = "permission denied ($type): $data[1]"; + } + break; + case 'chmod': + // check that file is writable + if (!is_writable($data[1])) { + $errors[] = "permission denied ($type): $data[1] " . decoct($data[0]); + } + break; + case 'delete': + if (!file_exists($data[0])) { + $this->log(2, "warning: file $data[0] doesn't exist, can't be deleted"); + } + // check that directory is writable + if (file_exists($data[0]) && !is_writable(dirname($data[0]))) { + $errors[] = "permission denied ($type): $data[0]"; + } + break; + } + + } + // }}} + $m = sizeof($errors); + if ($m > 0) { + foreach ($errors as $error) { + $this->log(1, $error); + } + return false; + } + // {{{ really commit the transaction + foreach ($this->file_operations as $tr) { + list($type, $data) = $tr; + switch ($type) { + case 'rename': + @unlink($data[1]); + @rename($data[0], $data[1]); + $this->log(3, "+ mv $data[0] $data[1]"); + break; + case 'chmod': + @chmod($data[1], $data[0]); + $octmode = decoct($data[0]); + $this->log(3, "+ chmod $octmode $data[1]"); + break; + case 'delete': + @unlink($data[0]); + $this->log(3, "+ rm $data[0]"); + break; + case 'rmdir': + @rmdir($data[0]); + $this->log(3, "+ rmdir $data[0]"); + break; + case 'installed_as': + $this->pkginfo['filelist'][$data[0]]['installed_as'] = $data[1]; + if (!isset($this->pkginfo['filelist']['dirtree'][dirname($data[1])])) { + $this->pkginfo['filelist']['dirtree'][dirname($data[1])] = true; + while(!empty($data[3]) && $data[3] != '/' && $data[3] != '\\' + && $data[3] != '.') { + $this->pkginfo['filelist']['dirtree'] + [$this->_prependPath($data[3], $data[2])] = true; + $data[3] = dirname($data[3]); + } + } + break; + } + } + // }}} + $this->log(2, "successfully committed $n file operations"); + $this->file_operations = array(); + return true; + } + + // }}} + // {{{ rollbackFileTransaction() + + function rollbackFileTransaction() + { + $n = count($this->file_operations); + $this->log(2, "rolling back $n file operations"); + foreach ($this->file_operations as $tr) { + list($type, $data) = $tr; + switch ($type) { + case 'rename': + @unlink($data[0]); + $this->log(3, "+ rm $data[0]"); + break; + case 'mkdir': + @rmdir($data[0]); + $this->log(3, "+ rmdir $data[0]"); + break; + case 'chmod': + break; + case 'delete': + break; + case 'installed_as': + if (isset($this->pkginfo['filelist'])) { + unset($this->pkginfo['filelist'][$data[0]]['installed_as']); + } + if (isset($this->pkginfo['filelist']['dirtree'][dirname($data[1])])) { + unset($this->pkginfo['filelist']['dirtree'][dirname($data[1])]); + while(!empty($data[3]) && $data[3] != '/' && $data[3] != '\\' + && $data[3] != '.') { + unset($this->pkginfo['filelist']['dirtree'] + [$this->_prependPath($data[3], $data[2])]); + $data[3] = dirname($data[3]); + } + } + if (isset($this->pkginfo['filelist']['dirtree']) + && !count($this->pkginfo['filelist']['dirtree'])) { + unset($this->pkginfo['filelist']['dirtree']); + } + break; + } + } + $this->file_operations = array(); + } + + // }}} + // {{{ mkDirHier($dir) + + function mkDirHier($dir) + { + $this->addFileOperation('mkdir', array($dir)); + return parent::mkDirHier($dir); + } + + // }}} + // {{{ download() + + /** + * Download any files and their dependencies, if necessary + * + * @param array a mixed list of package names, local files, or package.xml + * @param PEAR_Config + * @param array options from the command line + * @param array this is the array that will be populated with packages to + * install. Format of each entry: + * + * + * array('pkg' => 'package_name', 'file' => '/path/to/local/file', + * 'info' => array() // parsed package.xml + * ); + * + * @param array this will be populated with any error messages + * @param false private recursion variable + * @param false private recursion variable + * @param false private recursion variable + * @deprecated in favor of PEAR_Downloader + */ + function download($packages, $options, &$config, &$installpackages, + &$errors, $installed = false, $willinstall = false, $state = false) + { + // trickiness: initialize here + parent::PEAR_Downloader($this->ui, $options, $config); + $ret = parent::download($packages); + $errors = $this->getErrorMsgs(); + $installpackages = $this->getDownloadedPackages(); + trigger_error("PEAR Warning: PEAR_Installer::download() is deprecated " . + "in favor of PEAR_Downloader class", E_USER_WARNING); + return $ret; + } + + // }}} + // {{{ install() + + /** + * Installs the files within the package file specified. + * + * @param string $pkgfile path to the package file + * @param array $options + * recognized options: + * - installroot : optional prefix directory for installation + * - force : force installation + * - register-only : update registry but don't install files + * - upgrade : upgrade existing install + * - soft : fail silently + * - nodeps : ignore dependency conflicts/missing dependencies + * - alldeps : install all dependencies + * - onlyreqdeps : install only required dependencies + * + * @return array|PEAR_Error package info if successful + */ + + function install($pkgfile, $options = array()) + { + $php_dir = $this->config->get('php_dir'); + if (isset($options['installroot'])) { + if (substr($options['installroot'], -1) == DIRECTORY_SEPARATOR) { + $options['installroot'] = substr($options['installroot'], 0, -1); + } + $php_dir = $this->_prependPath($php_dir, $options['installroot']); + $this->installroot = $options['installroot']; + } else { + $this->installroot = ''; + } + $this->registry = &new PEAR_Registry($php_dir); + // ==> XXX should be removed later on + $flag_old_format = false; + + if (substr($pkgfile, -4) == '.xml') { + $descfile = $pkgfile; + } else { + // {{{ Decompress pack in tmp dir ------------------------------------- + + // To allow relative package file names + $pkgfile = realpath($pkgfile); + + if (PEAR::isError($tmpdir = System::mktemp('-d'))) { + return $tmpdir; + } + $this->log(3, '+ tmp dir created at ' . $tmpdir); + + $tar = new Archive_Tar($pkgfile); + if (!@$tar->extract($tmpdir)) { + return $this->raiseError("unable to unpack $pkgfile"); + } + + // {{{ Look for existing package file + $descfile = $tmpdir . DIRECTORY_SEPARATOR . 'package.xml'; + + if (!is_file($descfile)) { + // ----- Look for old package archive format + // In this format the package.xml file was inside the + // Package-n.n directory + $dp = opendir($tmpdir); + do { + $pkgdir = readdir($dp); + } while ($pkgdir{0} == '.'); + + $descfile = $tmpdir . DIRECTORY_SEPARATOR . $pkgdir . DIRECTORY_SEPARATOR . 'package.xml'; + $flag_old_format = true; + $this->log(0, "warning : you are using an archive with an old format"); + } + // }}} + // <== XXX This part should be removed later on + // }}} + } + + if (!is_file($descfile)) { + return $this->raiseError("no package.xml file after extracting the archive"); + } + + // Parse xml file ----------------------------------------------- + $pkginfo = $this->infoFromDescriptionFile($descfile); + if (PEAR::isError($pkginfo)) { + return $pkginfo; + } + $this->validatePackageInfo($pkginfo, $errors, $warnings); + // XXX We allow warnings, do we have to do it? + if (count($errors)) { + if (empty($options['force'])) { + return $this->raiseError("The following errors where found (use force option to install anyway):\n". + implode("\n", $errors)); + } else { + $this->log(0, "warning : the following errors were found:\n". + implode("\n", $errors)); + } + } + + $pkgname = $pkginfo['package']; + + // {{{ Check dependencies ------------------------------------------- + if (isset($pkginfo['release_deps']) && empty($options['nodeps'])) { + $dep_errors = ''; + $error = $this->checkDeps($pkginfo, $dep_errors); + if ($error == true) { + if (empty($options['soft'])) { + $this->log(0, substr($dep_errors, 1)); + } + return $this->raiseError("$pkgname: Dependencies failed"); + } else if (!empty($dep_errors)) { + // Print optional dependencies + if (empty($options['soft'])) { + $this->log(0, $dep_errors); + } + } + } + // }}} + + // {{{ checks to do when not in "force" mode + if (empty($options['force'])) { + $test = $this->registry->checkFileMap($pkginfo); + if (sizeof($test)) { + $tmp = $test; + foreach ($tmp as $file => $pkg) { + if ($pkg == $pkgname) { + unset($test[$file]); + } + } + if (sizeof($test)) { + $msg = "$pkgname: conflicting files found:\n"; + $longest = max(array_map("strlen", array_keys($test))); + $fmt = "%${longest}s (%s)\n"; + foreach ($test as $file => $pkg) { + $msg .= sprintf($fmt, $file, $pkg); + } + return $this->raiseError($msg); + } + } + } + // }}} + + $this->startFileTransaction(); + + if (empty($options['upgrade'])) { + // checks to do only when installing new packages + if (empty($options['force']) && $this->registry->packageExists($pkgname)) { + return $this->raiseError("$pkgname already installed"); + } + } else { + if ($this->registry->packageExists($pkgname)) { + $v1 = $this->registry->packageInfo($pkgname, 'version'); + $v2 = $pkginfo['version']; + $cmp = version_compare("$v1", "$v2", 'gt'); + if (empty($options['force']) && !version_compare("$v2", "$v1", 'gt')) { + return $this->raiseError("upgrade to a newer version ($v2 is not newer than $v1)"); + } + if (empty($options['register-only'])) { + // when upgrading, remove old release's files first: + if (PEAR::isError($err = $this->_deletePackageFiles($pkgname))) { + return $this->raiseError($err); + } + } + } + } + + // {{{ Copy files to dest dir --------------------------------------- + + // info from the package it self we want to access from _installFile + $this->pkginfo = &$pkginfo; + // used to determine whether we should build any C code + $this->source_files = 0; + + if (empty($options['register-only'])) { + if (!is_dir($php_dir)) { + return $this->raiseError("no script destination directory\n", + null, PEAR_ERROR_DIE); + } + + $tmp_path = dirname($descfile); + if (substr($pkgfile, -4) != '.xml') { + $tmp_path .= DIRECTORY_SEPARATOR . $pkgname . '-' . $pkginfo['version']; + } + + // ==> XXX This part should be removed later on + if ($flag_old_format) { + $tmp_path = dirname($descfile); + } + // <== XXX This part should be removed later on + + // {{{ install files + foreach ($pkginfo['filelist'] as $file => $atts) { + $this->expectError(PEAR_INSTALLER_FAILED); + $res = $this->_installFile($file, $atts, $tmp_path, $options); + $this->popExpect(); + if (PEAR::isError($res)) { + if (empty($options['ignore-errors'])) { + $this->rollbackFileTransaction(); + if ($res->getMessage() == "file does not exist") { + $this->raiseError("file $file in package.xml does not exist"); + } + return $this->raiseError($res); + } else { + $this->log(0, "Warning: " . $res->getMessage()); + } + } + if ($res != PEAR_INSTALLER_OK) { + // Do not register files that were not installed + unset($pkginfo['filelist'][$file]); + } + } + // }}} + + // {{{ compile and install source files + if ($this->source_files > 0 && empty($options['nobuild'])) { + $this->log(1, "$this->source_files source files, building"); + $bob = &new PEAR_Builder($this->ui); + $bob->debug = $this->debug; + $built = $bob->build($descfile, array(&$this, '_buildCallback')); + if (PEAR::isError($built)) { + $this->rollbackFileTransaction(); + return $built; + } + $this->log(1, "\nBuild process completed successfully"); + foreach ($built as $ext) { + $bn = basename($ext['file']); + list($_ext_name, ) = explode('.', $bn); + if (extension_loaded($_ext_name)) { + $this->raiseError("Extension '$_ext_name' already loaded. Please unload it ". + "in your php.ini file prior to install or upgrade it."); + } + // extension dir must be created if it doesn't exist + // patch by Tomas Cox (modified by Greg Beaver) + $ext_dir = $this->config->get('ext_dir'); + if (!@is_dir($ext_dir) && !System::mkdir(array('-p', $ext_dir))) { + $this->log(3, "+ mkdir -p $ext_dir"); + return $this->raiseError("failed to create extension dir '$ext_dir'"); + } + $dest = $ext_dir . DIRECTORY_SEPARATOR . $bn; + $this->log(1, "Installing '$bn' at ext_dir ($dest)"); + $this->log(3, "+ cp $ext[file] ext_dir ($dest)"); + $copyto = $this->_prependPath($dest, $this->installroot); + if (!@copy($ext['file'], $copyto)) { + $this->rollbackFileTransaction(); + return $this->raiseError("failed to copy $bn to $copyto"); + } + $pkginfo['filelist'][$bn] = array( + 'role' => 'ext', + 'installed_as' => $dest, + 'php_api' => $ext['php_api'], + 'zend_mod_api' => $ext['zend_mod_api'], + 'zend_ext_api' => $ext['zend_ext_api'], + ); + } + } + // }}} + } + + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + return $this->raiseError("commit failed", PEAR_INSTALLER_FAILED); + } + // }}} + + $ret = false; + // {{{ Register that the package is installed ----------------------- + if (empty($options['upgrade'])) { + // if 'force' is used, replace the info in registry + if (!empty($options['force']) && $this->registry->packageExists($pkgname)) { + $this->registry->deletePackage($pkgname); + } + $ret = $this->registry->addPackage($pkgname, $pkginfo); + } else { + // new: upgrade installs a package if it isn't installed + if (!$this->registry->packageExists($pkgname)) { + $ret = $this->registry->addPackage($pkgname, $pkginfo); + } else { + $ret = $this->registry->updatePackage($pkgname, $pkginfo, false); + } + } + if (!$ret) { + return $this->raiseError("Adding package $pkgname to registry failed"); + } + // }}} + return $pkginfo; + } + + // }}} + // {{{ uninstall() + + /** + * Uninstall a package + * + * This method removes all files installed by the application, and then + * removes any empty directories. + * @param string package name + * @param array Command-line options. Possibilities include: + * + * - installroot: base installation dir, if not the default + * - nodeps: do not process dependencies of other packages to ensure + * uninstallation does not break things + */ + function uninstall($package, $options = array()) + { + $php_dir = $this->config->get('php_dir'); + if (isset($options['installroot'])) { + if (substr($options['installroot'], -1) == DIRECTORY_SEPARATOR) { + $options['installroot'] = substr($options['installroot'], 0, -1); + } + $this->installroot = $options['installroot']; + $php_dir = $this->_prependPath($php_dir, $this->installroot); + } else { + $this->installroot = ''; + } + $this->registry = &new PEAR_Registry($php_dir); + $filelist = $this->registry->packageInfo($package, 'filelist'); + if ($filelist == null) { + return $this->raiseError("$package not installed"); + } + if (empty($options['nodeps'])) { + $depchecker = &new PEAR_Dependency($this->registry); + $error = $depchecker->checkPackageUninstall($errors, $warning, $package); + if ($error) { + return $this->raiseError($errors . 'uninstall failed'); + } + if ($warning) { + $this->log(0, $warning); + } + } + // {{{ Delete the files + $this->startFileTransaction(); + if (PEAR::isError($err = $this->_deletePackageFiles($package))) { + $this->rollbackFileTransaction(); + return $this->raiseError($err); + } + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + return $this->raiseError("uninstall failed"); + } else { + $this->startFileTransaction(); + if (!isset($filelist['dirtree']) || !count($filelist['dirtree'])) { + return $this->registry->deletePackage($package); + } + // attempt to delete empty directories + uksort($filelist['dirtree'], array($this, '_sortDirs')); + foreach($filelist['dirtree'] as $dir => $notused) { + $this->addFileOperation('rmdir', array($dir)); + } + if (!$this->commitFileTransaction()) { + $this->rollbackFileTransaction(); + } + } + // }}} + + // Register that the package is no longer installed + return $this->registry->deletePackage($package); + } + + // }}} + // {{{ _sortDirs() + function _sortDirs($a, $b) + { + if (strnatcmp($a, $b) == -1) return 1; + if (strnatcmp($a, $b) == 1) return -1; + return 0; + } + + // }}} + // {{{ checkDeps() + + /** + * Check if the package meets all dependencies + * + * @param array Package information (passed by reference) + * @param string Error message (passed by reference) + * @return boolean False when no error occured, otherwise true + */ + function checkDeps(&$pkginfo, &$errors) + { + if (empty($this->registry)) { + $this->registry = &new PEAR_Registry($this->config->get('php_dir')); + } + $depchecker = &new PEAR_Dependency($this->registry); + $error = $errors = ''; + $failed_deps = $optional_deps = array(); + if (is_array($pkginfo['release_deps'])) { + foreach($pkginfo['release_deps'] as $dep) { + $code = $depchecker->callCheckMethod($error, $dep); + if ($code) { + if (isset($dep['optional']) && $dep['optional'] == 'yes') { + $optional_deps[] = array($dep, $code, $error); + } else { + $failed_deps[] = array($dep, $code, $error); + } + } + } + // {{{ failed dependencies + $n = count($failed_deps); + if ($n > 0) { + for ($i = 0; $i < $n; $i++) { + if (isset($failed_deps[$i]['type'])) { + $type = $failed_deps[$i]['type']; + } else { + $type = 'pkg'; + } + switch ($failed_deps[$i][1]) { + case PEAR_DEPENDENCY_MISSING: + if ($type == 'pkg') { + // install + } + $errors .= "\n" . $failed_deps[$i][2]; + break; + case PEAR_DEPENDENCY_UPGRADE_MINOR: + if ($type == 'pkg') { + // upgrade + } + $errors .= "\n" . $failed_deps[$i][2]; + break; + default: + $errors .= "\n" . $failed_deps[$i][2]; + break; + } + } + return true; + } + // }}} + + // {{{ optional dependencies + $count_optional = count($optional_deps); + if ($count_optional > 0) { + $errors = "Optional dependencies:"; + + for ($i = 0; $i < $count_optional; $i++) { + if (isset($optional_deps[$i]['type'])) { + $type = $optional_deps[$i]['type']; + } else { + $type = 'pkg'; + } + switch ($optional_deps[$i][1]) { + case PEAR_DEPENDENCY_MISSING: + case PEAR_DEPENDENCY_UPGRADE_MINOR: + default: + $errors .= "\n" . $optional_deps[$i][2]; + break; + } + } + return false; + } + // }}} + } + return false; + } + + // }}} + // {{{ _buildCallback() + + function _buildCallback($what, $data) + { + if (($what == 'cmdoutput' && $this->debug > 1) || + ($what == 'output' && $this->debug > 0)) { + $this->ui->outputData(rtrim($data), 'build'); + } + } + + // }}} +} + +// {{{ md5_file() utility function +if (!function_exists("md5_file")) { + function md5_file($filename) { + $fp = fopen($filename, "r"); + if (!$fp) return null; + $contents = fread($fp, filesize($filename)); + fclose($fp); + return md5($contents); + } +} +// }}} + +?> diff --git a/common/PEAR/PEAR/Packager.php b/common/PEAR/PEAR/Packager.php new file mode 100644 index 0000000..65db7dd --- /dev/null +++ b/common/PEAR/PEAR/Packager.php @@ -0,0 +1,165 @@ + | +// | Tomas V.V.Cox | +// +----------------------------------------------------------------------+ +// +// $Id: Packager.php,v 1.43.2.12 2004/01/26 01:26:46 pajoye Exp $ + +require_once 'PEAR/Common.php'; +require_once 'System.php'; + +/** + * Administration class used to make a PEAR release tarball. + * + * TODO: + * - add an extra param the dir where to place the created package + * + * @since PHP 4.0.2 + * @author Stig Bakken + */ +class PEAR_Packager extends PEAR_Common +{ + // {{{ constructor + + function PEAR_Packager() + { + parent::PEAR_Common(); + } + + // }}} + // {{{ destructor + + function _PEAR_Packager() + { + parent::_PEAR_Common(); + } + + // }}} + + // {{{ package() + + function package($pkgfile = null, $compress = true) + { + // {{{ validate supplied package.xml file + if (empty($pkgfile)) { + $pkgfile = 'package.xml'; + } + // $this->pkginfo gets populated inside + $pkginfo = $this->infoFromDescriptionFile($pkgfile); + if (PEAR::isError($pkginfo)) { + return $this->raiseError($pkginfo); + } + + $pkgdir = dirname(realpath($pkgfile)); + $pkgfile = basename($pkgfile); + + $errors = $warnings = array(); + $this->validatePackageInfo($pkginfo, $errors, $warnings, $pkgdir); + foreach ($warnings as $w) { + $this->log(1, "Warning: $w"); + } + foreach ($errors as $e) { + $this->log(0, "Error: $e"); + } + if (sizeof($errors) > 0) { + return $this->raiseError('Errors in package'); + } + // }}} + + $pkgver = $pkginfo['package'] . '-' . $pkginfo['version']; + + // {{{ Create the package file list + $filelist = array(); + $i = 0; + + foreach ($pkginfo['filelist'] as $fname => $atts) { + $file = $pkgdir . DIRECTORY_SEPARATOR . $fname; + if (!file_exists($file)) { + return $this->raiseError("File does not exist: $fname"); + } else { + $filelist[$i++] = $file; + if (empty($pkginfo['filelist'][$fname]['md5sum'])) { + $md5sum = md5_file($file); + $tpkginfo['filelist'][$fname]['md5sum'] = $md5sum; + } + $this->log(2, "Adding file $fname"); + } + } + // }}} + + // {{{ regenerate package.xml + $new_xml = $this->xmlFromInfo($pkginfo); + if (PEAR::isError($new_xml)) { + return $this->raiseError($new_xml); + } + if (!($tmpdir = System::mktemp(array('-d')))) { + return $this->raiseError("PEAR_Packager: mktemp failed"); + } + $newpkgfile = $tmpdir . DIRECTORY_SEPARATOR . 'package.xml'; + $np = @fopen($newpkgfile, 'wb'); + if (!$np) { + return $this->raiseError("PEAR_Packager: unable to rewrite $pkgfile as $newpkgfile"); + } + fwrite($np, $new_xml); + fclose($np); + // }}} + + // {{{ TAR the Package ------------------------------------------- + $ext = $compress ? '.tgz' : '.tar'; + $dest_package = getcwd() . DIRECTORY_SEPARATOR . $pkgver . $ext; + $tar =& new Archive_Tar($dest_package, $compress); + $tar->setErrorHandling(PEAR_ERROR_RETURN); // XXX Don't print errors + // ----- Creates with the package.xml file + $ok = $tar->createModify(array($newpkgfile), '', $tmpdir); + if (PEAR::isError($ok)) { + return $this->raiseError($ok); + } elseif (!$ok) { + return $this->raiseError('PEAR_Packager: tarball creation failed'); + } + // ----- Add the content of the package + if (!$tar->addModify($filelist, $pkgver, $pkgdir)) { + return $this->raiseError('PEAR_Packager: tarball creation failed'); + } + $this->log(1, "Package $dest_package done"); + if (file_exists("$pkgdir/CVS/Root")) { + $cvsversion = preg_replace('/[^a-z0-9]/i', '_', $pkginfo['version']); + $cvstag = "RELEASE_$cvsversion"; + $this->log(1, "Tag the released code with `pear cvstag $pkgfile'"); + $this->log(1, "(or set the CVS tag $cvstag by hand)"); + } + // }}} + + return $dest_package; + } + + // }}} +} + +// {{{ md5_file() utility function +if (!function_exists('md5_file')) { + function md5_file($file) { + if (!$fd = @fopen($file, 'r')) { + return false; + } + $md5 = md5(fread($fd, filesize($file))); + fclose($fd); + return $md5; + } +} +// }}} + +?> diff --git a/common/PEAR/PEAR/Registry.php b/common/PEAR/PEAR/Registry.php new file mode 100644 index 0000000..3bc6acb --- /dev/null +++ b/common/PEAR/PEAR/Registry.php @@ -0,0 +1,533 @@ + | +// | Tomas V.V.Cox | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: Registry.php,v 1.35.2.17 2004/01/26 01:26:46 pajoye Exp $ + +/* +TODO: + - Transform into singleton() + - Add application level lock (avoid change the registry from the cmdline + while using the GTK interface, for ex.) +*/ +require_once "System.php"; +require_once "PEAR.php"; + +define('PEAR_REGISTRY_ERROR_LOCK', -2); +define('PEAR_REGISTRY_ERROR_FORMAT', -3); +define('PEAR_REGISTRY_ERROR_FILE', -4); + +/** + * Administration class used to maintain the installed package database. + */ +class PEAR_Registry extends PEAR +{ + // {{{ properties + + /** Directory where registry files are stored. + * @var string + */ + var $statedir = ''; + + /** File where the file map is stored + * @var string + */ + var $filemap = ''; + + /** Name of file used for locking the registry + * @var string + */ + var $lockfile = ''; + + /** File descriptor used during locking + * @var resource + */ + var $lock_fp = null; + + /** Mode used during locking + * @var int + */ + var $lock_mode = 0; // XXX UNUSED + + /** Cache of package information. Structure: + * array( + * 'package' => array('id' => ... ), + * ... ) + * @var array + */ + var $pkginfo_cache = array(); + + /** Cache of file map. Structure: + * array( '/path/to/file' => 'package', ... ) + * @var array + */ + var $filemap_cache = array(); + + // }}} + + // {{{ constructor + + /** + * PEAR_Registry constructor. + * + * @param string (optional) PEAR install directory (for .php files) + * + * @access public + */ + function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR) + { + parent::PEAR(); + $ds = DIRECTORY_SEPARATOR; + $this->install_dir = $pear_install_dir; + $this->statedir = $pear_install_dir.$ds.'.registry'; + $this->filemap = $pear_install_dir.$ds.'.filemap'; + $this->lockfile = $pear_install_dir.$ds.'.lock'; + + // XXX Compatibility code should be removed in the future + // rename all registry files if any to lowercase + if (!OS_WINDOWS && $handle = @opendir($this->statedir)) { + $dest = $this->statedir . DIRECTORY_SEPARATOR; + while (false !== ($file = readdir($handle))) { + if (preg_match('/^.*[A-Z].*\.reg$/', $file)) { + rename($dest . $file, $dest . strtolower($file)); + } + } + closedir($handle); + } + if (!file_exists($this->filemap)) { + $this->rebuildFileMap(); + } + } + + // }}} + // {{{ destructor + + /** + * PEAR_Registry destructor. Makes sure no locks are forgotten. + * + * @access private + */ + function _PEAR_Registry() + { + parent::_PEAR(); + if (is_resource($this->lock_fp)) { + $this->_unlock(); + } + } + + // }}} + + // {{{ _assertStateDir() + + /** + * Make sure the directory where we keep registry files exists. + * + * @return bool TRUE if directory exists, FALSE if it could not be + * created + * + * @access private + */ + function _assertStateDir() + { + if (!@is_dir($this->statedir)) { + if (!System::mkdir(array('-p', $this->statedir))) { + return $this->raiseError("could not create directory '{$this->statedir}'"); + } + } + return true; + } + + // }}} + // {{{ _packageFileName() + + /** + * Get the name of the file where data for a given package is stored. + * + * @param string package name + * + * @return string registry file name + * + * @access public + */ + function _packageFileName($package) + { + return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg'; + } + + // }}} + // {{{ _openPackageFile() + + function _openPackageFile($package, $mode) + { + $this->_assertStateDir(); + $file = $this->_packageFileName($package); + $fp = @fopen($file, $mode); + if (!$fp) { + return null; + } + return $fp; + } + + // }}} + // {{{ _closePackageFile() + + function _closePackageFile($fp) + { + fclose($fp); + } + + // }}} + // {{{ rebuildFileMap() + + function rebuildFileMap() + { + $packages = $this->listPackages(); + $files = array(); + foreach ($packages as $package) { + $version = $this->packageInfo($package, 'version'); + $filelist = $this->packageInfo($package, 'filelist'); + if (!is_array($filelist)) { + continue; + } + foreach ($filelist as $name => $attrs) { + if (isset($attrs['role']) && $attrs['role'] != 'php') { + continue; + } + if (isset($attrs['baseinstalldir'])) { + $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; + } else { + $file = $name; + } + $file = preg_replace(',^/+,', '', $file); + $files[$file] = $package; + } + } + $this->_assertStateDir(); + $fp = @fopen($this->filemap, 'wb'); + if (!$fp) { + return false; + } + $this->filemap_cache = $files; + fwrite($fp, serialize($files)); + fclose($fp); + return true; + } + + // }}} + // {{{ readFileMap() + + function readFileMap() + { + $fp = @fopen($this->filemap, 'r'); + if (!$fp) { + return $this->raiseError('PEAR_Registry: could not open filemap', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); + } + $fsize = filesize($this->filemap); + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + $data = fread($fp, $fsize); + set_magic_quotes_runtime($rt); + fclose($fp); + $tmp = unserialize($data); + if (!$tmp && $fsize > 7) { + return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data); + } + $this->filemap_cache = $tmp; + return true; + } + + // }}} + // {{{ _lock() + + /** + * Lock the registry. + * + * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN. + * See flock manual for more information. + * + * @return bool TRUE on success, FALSE if locking failed, or a + * PEAR error if some other error occurs (such as the + * lock file not being writable). + * + * @access private + */ + function _lock($mode = LOCK_EX) + { + if (!eregi('Windows 9', php_uname())) { + if ($mode != LOCK_UN && is_resource($this->lock_fp)) { + // XXX does not check type of lock (LOCK_SH/LOCK_EX) + return true; + } + if (PEAR::isError($err = $this->_assertStateDir())) { + return $err; + } + $open_mode = 'w'; + // XXX People reported problems with LOCK_SH and 'w' + if ($mode === LOCK_SH || $mode === LOCK_UN) { + if (@!is_file($this->lockfile)) { + touch($this->lockfile); + } + $open_mode = 'r'; + } + + $this->lock_fp = @fopen($this->lockfile, $open_mode); + + if (!is_resource($this->lock_fp)) { + return $this->raiseError("could not create lock file" . + (isset($php_errormsg) ? ": " . $php_errormsg : "")); + } + if (!(int)flock($this->lock_fp, $mode)) { + switch ($mode) { + case LOCK_SH: $str = 'shared'; break; + case LOCK_EX: $str = 'exclusive'; break; + case LOCK_UN: $str = 'unlock'; break; + default: $str = 'unknown'; break; + } + return $this->raiseError("could not acquire $str lock ($this->lockfile)", + PEAR_REGISTRY_ERROR_LOCK); + } + } + return true; + } + + // }}} + // {{{ _unlock() + + function _unlock() + { + $ret = $this->_lock(LOCK_UN); + $this->lock_fp = null; + return $ret; + } + + // }}} + // {{{ _packageExists() + + function _packageExists($package) + { + return file_exists($this->_packageFileName($package)); + } + + // }}} + // {{{ _packageInfo() + + function _packageInfo($package = null, $key = null) + { + if ($package === null) { + return array_map(array($this, '_packageInfo'), + $this->_listPackages()); + } + $fp = $this->_openPackageFile($package, 'r'); + if ($fp === null) { + return null; + } + $rt = get_magic_quotes_runtime(); + set_magic_quotes_runtime(0); + $data = fread($fp, filesize($this->_packageFileName($package))); + set_magic_quotes_runtime($rt); + $this->_closePackageFile($fp); + $data = unserialize($data); + if ($key === null) { + return $data; + } + if (isset($data[$key])) { + return $data[$key]; + } + return null; + } + + // }}} + // {{{ _listPackages() + + function _listPackages() + { + $pkglist = array(); + $dp = @opendir($this->statedir); + if (!$dp) { + return $pkglist; + } + while ($ent = readdir($dp)) { + if ($ent{0} == '.' || substr($ent, -4) != '.reg') { + continue; + } + $pkglist[] = substr($ent, 0, -4); + } + return $pkglist; + } + + // }}} + + // {{{ packageExists() + + function packageExists($package) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_packageExists($package); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ packageInfo() + + function packageInfo($package = null, $key = null) + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_packageInfo($package, $key); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ listPackages() + + function listPackages() + { + if (PEAR::isError($e = $this->_lock(LOCK_SH))) { + return $e; + } + $ret = $this->_listPackages(); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ addPackage() + + function addPackage($package, $info) + { + if ($this->packageExists($package)) { + return false; + } + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $fp = $this->_openPackageFile($package, 'wb'); + if ($fp === null) { + $this->_unlock(); + return false; + } + $info['_lastmodified'] = time(); + fwrite($fp, serialize($info)); + $this->_closePackageFile($fp); + $this->_unlock(); + return true; + } + + // }}} + // {{{ deletePackage() + + function deletePackage($package) + { + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $file = $this->_packageFileName($package); + $ret = @unlink($file); + $this->rebuildFileMap(); + $this->_unlock(); + return $ret; + } + + // }}} + // {{{ updatePackage() + + function updatePackage($package, $info, $merge = true) + { + $oldinfo = $this->packageInfo($package); + if (empty($oldinfo)) { + return false; + } + if (PEAR::isError($e = $this->_lock(LOCK_EX))) { + return $e; + } + $fp = $this->_openPackageFile($package, 'w'); + if ($fp === null) { + $this->_unlock(); + return false; + } + $info['_lastmodified'] = time(); + if ($merge) { + fwrite($fp, serialize(array_merge($oldinfo, $info))); + } else { + fwrite($fp, serialize($info)); + } + $this->_closePackageFile($fp); + if (isset($info['filelist'])) { + $this->rebuildFileMap(); + } + $this->_unlock(); + return true; + } + + // }}} + // {{{ checkFileMap() + + /** + * Test whether a file belongs to a package. + * + * @param string $path file path, absolute or relative to the pear + * install dir + * + * @return string which package the file belongs to, or an empty + * string if the file does not belong to an installed package + * + * @access public + */ + function checkFileMap($path) + { + if (is_array($path)) { + static $notempty; + if (empty($notempty)) { + $notempty = create_function('$a','return !empty($a);'); + } + $pkgs = array(); + foreach ($path as $name => $attrs) { + if (is_array($attrs) && isset($attrs['baseinstalldir'])) { + $name = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; + } + $pkgs[$name] = $this->checkFileMap($name); + } + return array_filter($pkgs, $notempty); + } + if (empty($this->filemap_cache) && PEAR::isError($this->readFileMap())) { + return $err; + } + if (isset($this->filemap_cache[$path])) { + return $this->filemap_cache[$path]; + } + $l = strlen($this->install_dir); + if (substr($path, 0, $l) == $this->install_dir) { + $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l)); + } + if (isset($this->filemap_cache[$path])) { + return $this->filemap_cache[$path]; + } + return ''; + } + + // }}} + +} + +?> diff --git a/common/PEAR/PEAR/Remote.php b/common/PEAR/PEAR/Remote.php new file mode 100644 index 0000000..a54e314 --- /dev/null +++ b/common/PEAR/PEAR/Remote.php @@ -0,0 +1,394 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Remote.php,v 1.34.2.14 2004/06/08 18:04:00 cellog Exp $ + +require_once 'PEAR.php'; +require_once 'PEAR/Config.php'; + +/** + * This is a class for doing remote operations against the central + * PEAR database. + * + * @nodep XML_RPC_Value + * @nodep XML_RPC_Message + * @nodep XML_RPC_Client + */ +class PEAR_Remote extends PEAR +{ + // {{{ properties + + var $config = null; + var $cache = null; + + // }}} + + // {{{ PEAR_Remote(config_object) + + function PEAR_Remote(&$config) + { + $this->PEAR(); + $this->config = &$config; + } + + // }}} + + // {{{ getCache() + + + function getCache($args) + { + $id = md5(serialize($args)); + $cachedir = $this->config->get('cache_dir'); + $filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id; + if (!file_exists($filename)) { + return null; + }; + + $fp = fopen($filename, 'rb'); + if (!$fp) { + return null; + } + $content = fread($fp, filesize($filename)); + fclose($fp); + $result = array( + 'age' => time() - filemtime($filename), + 'lastChange' => filemtime($filename), + 'content' => unserialize($content), + ); + return $result; + } + + // }}} + + // {{{ saveCache() + + function saveCache($args, $data) + { + $id = md5(serialize($args)); + $cachedir = $this->config->get('cache_dir'); + if (!file_exists($cachedir)) { + System::mkdir(array('-p', $cachedir)); + } + $filename = $cachedir.'/xmlrpc_cache_'.$id; + + $fp = @fopen($filename, "wb"); + if ($fp) { + fwrite($fp, serialize($data)); + fclose($fp); + }; + } + + // }}} + + // {{{ call(method, [args...]) + + function call($method) + { + $_args = $args = func_get_args(); + + $this->cache = $this->getCache($args); + $cachettl = $this->config->get('cache_ttl'); + // If cache is newer than $cachettl seconds, we use the cache! + if ($this->cache !== null && $this->cache['age'] < $cachettl) { + return $this->cache['content']; + }; + + if (extension_loaded("xmlrpc")) { + $result = call_user_func_array(array(&$this, 'call_epi'), $args); + if (!PEAR::isError($result)) { + $this->saveCache($_args, $result); + }; + return $result; + } + if (!@include_once("XML/RPC.php")) { + return $this->raiseError("For this remote PEAR operation you need to install the XML_RPC package"); + } + array_shift($args); + $server_host = $this->config->get('master_server'); + $username = $this->config->get('username'); + $password = $this->config->get('password'); + $eargs = array(); + foreach($args as $arg) $eargs[] = $this->_encode($arg); + $f = new XML_RPC_Message($method, $eargs); + if ($this->cache !== null) { + $maxAge = '?maxAge='.$this->cache['lastChange']; + } else { + $maxAge = ''; + }; + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + if ($proxy = parse_url($this->config->get('http_proxy'))) { + $proxy_host = @$proxy['host']; + $proxy_port = @$proxy['port']; + $proxy_user = @urldecode(@$proxy['user']); + $proxy_pass = @urldecode(@$proxy['pass']); + } + $c = new XML_RPC_Client('/xmlrpc.php'.$maxAge, $server_host, 80, $proxy_host, $proxy_port, $proxy_user, $proxy_pass); + if ($username && $password) { + $c->setCredentials($username, $password); + } + if ($this->config->get('verbose') >= 3) { + $c->setDebug(1); + } + $r = $c->send($f); + if (!$r) { + return $this->raiseError("XML_RPC send failed"); + } + $v = $r->value(); + if ($e = $r->faultCode()) { + if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) { + return $this->cache['content']; + } + return $this->raiseError($r->faultString(), $e); + } + + $result = XML_RPC_decode($v); + $this->saveCache($_args, $result); + return $result; + } + + // }}} + + // {{{ call_epi(method, [args...]) + + function call_epi($method) + { + do { + if (extension_loaded("xmlrpc")) { + break; + } + if (OS_WINDOWS) { + $ext = 'dll'; + } elseif (PHP_OS == 'HP-UX') { + $ext = 'sl'; + } elseif (PHP_OS == 'AIX') { + $ext = 'a'; + } else { + $ext = 'so'; + } + $ext = OS_WINDOWS ? 'dll' : 'so'; + @dl("xmlrpc-epi.$ext"); + if (extension_loaded("xmlrpc")) { + break; + } + @dl("xmlrpc.$ext"); + if (extension_loaded("xmlrpc")) { + break; + } + return $this->raiseError("unable to load xmlrpc extension"); + } while (false); + $params = func_get_args(); + array_shift($params); + $method = str_replace("_", ".", $method); + $request = xmlrpc_encode_request($method, $params); + $server_host = $this->config->get("master_server"); + if (empty($server_host)) { + return $this->raiseError("PEAR_Remote::call: no master_server configured"); + } + $server_port = 80; + if ($http_proxy = $this->config->get('http_proxy')) { + $proxy = parse_url($http_proxy); + $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; + $proxy_host = @$proxy['host']; + $proxy_port = @$proxy['port']; + $proxy_user = @urldecode(@$proxy['user']); + $proxy_pass = @urldecode(@$proxy['pass']); + $fp = @fsockopen($proxy_host, $proxy_port); + $use_proxy = true; + } else { + $use_proxy = false; + $fp = @fsockopen($server_host, $server_port); + } + if (!$fp && $http_proxy) { + return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed"); + } elseif (!$fp) { + return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed"); + } + $len = strlen($request); + $req_headers = "Host: $server_host:$server_port\r\n" . + "Content-type: text/xml\r\n" . + "Content-length: $len\r\n"; + $username = $this->config->get('username'); + $password = $this->config->get('password'); + if ($username && $password) { + $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n"; + $tmp = base64_encode("$username:$password"); + $req_headers .= "Authorization: Basic $tmp\r\n"; + } + if ($this->cache !== null) { + $maxAge = '?maxAge='.$this->cache['lastChange']; + } else { + $maxAge = ''; + }; + + if ($use_proxy && $proxy_host != '' && $proxy_user != '') { + $req_headers .= 'Proxy-Authorization: Basic ' + .base64_encode($proxy_user.':'.$proxy_pass) + ."\r\n"; + } + + if ($this->config->get('verbose') > 3) { + print "XMLRPC REQUEST HEADERS:\n"; + var_dump($req_headers); + print "XMLRPC REQUEST BODY:\n"; + var_dump($request); + } + + if ($use_proxy && $proxy_host != '') { + $post_string = "POST http://".$server_host; + if ($proxy_port > '') { + $post_string .= ':'.$server_port; + } + } else { + $post_string = "POST "; + } + + fwrite($fp, ($post_string."/xmlrpc.php$maxAge HTTP/1.0\r\n$req_headers\r\n$request")); + $response = ''; + $line1 = fgets($fp, 2048); + if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) { + return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server"); + } + switch ($matches[1]) { + case "200": // OK + break; + case "304": // Not Modified + return $this->cache['content']; + case "401": // Unauthorized + if ($username && $password) { + return $this->raiseError("PEAR_Remote: authorization failed", 401); + } else { + return $this->raiseError("PEAR_Remote: authorization required, please log in first", 401); + } + default: + return $this->raiseError("PEAR_Remote: unexpected HTTP response", (int)$matches[1], null, null, "$matches[1] $matches[2]"); + } + while (trim(fgets($fp, 2048)) != ''); // skip rest of headers + while ($chunk = fread($fp, 10240)) { + $response .= $chunk; + } + fclose($fp); + if ($this->config->get('verbose') > 3) { + print "XMLRPC RESPONSE:\n"; + var_dump($response); + } + $ret = xmlrpc_decode($response); + if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) { + if ($ret['__PEAR_TYPE__'] == 'error') { + if (isset($ret['__PEAR_CLASS__'])) { + $class = $ret['__PEAR_CLASS__']; + } else { + $class = "PEAR_Error"; + } + if ($ret['code'] === '') $ret['code'] = null; + if ($ret['message'] === '') $ret['message'] = null; + if ($ret['userinfo'] === '') $ret['userinfo'] = null; + if (strtolower($class) == 'db_error') { + $ret = $this->raiseError(PEAR::errorMessage($ret['code']), + $ret['code'], null, null, + $ret['userinfo']); + } else { + $ret = $this->raiseError($ret['message'], $ret['code'], + null, null, $ret['userinfo']); + } + } + } elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0]) + && is_array($ret[0]) && + !empty($ret[0]['faultString']) && + !empty($ret[0]['faultCode'])) { + extract($ret[0]); + $faultString = "XML-RPC Server Fault: " . + str_replace("\n", " ", $faultString); + return $this->raiseError($faultString, $faultCode); + } + return $ret; + } + + // }}} + + // {{{ _encode + + // a slightly extended version of XML_RPC_encode + function _encode($php_val) + { + global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double; + global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct; + + $type = gettype($php_val); + $xmlrpcval = new XML_RPC_Value; + + switch($type) { + case "array": + reset($php_val); + $firstkey = key($php_val); + end($php_val); + $lastkey = key($php_val); + if ($firstkey === 0 && is_int($lastkey) && + ($lastkey + 1) == count($php_val)) { + $is_continuous = true; + reset($php_val); + $size = count($php_val); + for ($expect = 0; $expect < $size; $expect++, next($php_val)) { + if (key($php_val) !== $expect) { + $is_continuous = false; + break; + } + } + if ($is_continuous) { + reset($php_val); + $arr = array(); + while (list($k, $v) = each($php_val)) { + $arr[$k] = $this->_encode($v); + } + $xmlrpcval->addArray($arr); + break; + } + } + // fall though if not numerical and continuous + case "object": + $arr = array(); + while (list($k, $v) = each($php_val)) { + $arr[$k] = $this->_encode($v); + } + $xmlrpcval->addStruct($arr); + break; + case "integer": + $xmlrpcval->addScalar($php_val, $XML_RPC_Int); + break; + case "double": + $xmlrpcval->addScalar($php_val, $XML_RPC_Double); + break; + case "string": + case "NULL": + $xmlrpcval->addScalar($php_val, $XML_RPC_String); + break; + case "boolean": + $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean); + break; + case "unknown type": + default: + return null; + } + return $xmlrpcval; + } + + // }}} + +} + +?> diff --git a/common/PEAR/System.php b/common/PEAR/System.php new file mode 100644 index 0000000..bbca915 --- /dev/null +++ b/common/PEAR/System.php @@ -0,0 +1,540 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: System.php,v 1.21.2.15 2004/01/26 01:26:43 pajoye Exp $ +// + +require_once 'PEAR.php'; +require_once 'Console/Getopt.php'; + +$GLOBALS['_System_temp_files'] = array(); + +/** +* System offers cross plattform compatible system functions +* +* Static functions for different operations. Should work under +* Unix and Windows. The names and usage has been taken from its respectively +* GNU commands. The functions will return (bool) false on error and will +* trigger the error with the PHP trigger_error() function (you can silence +* the error by prefixing a '@' sign after the function call). +* +* Documentation on this class you can find in: +* http://pear.php.net/manual/ +* +* Example usage: +* if (!@System::rm('-r file1 dir1')) { +* print "could not delete file1 or dir1"; +* } +* +* In case you need to to pass file names with spaces, +* pass the params as an array: +* +* System::rm(array('-r', $file1, $dir1)); +* +* @package System +* @author Tomas V.V.Cox +* @version $Revision: 1.21.2.15 $ +* @access public +* @see http://pear.php.net/manual/ +*/ +class System +{ + /** + * returns the commandline arguments of a function + * + * @param string $argv the commandline + * @param string $short_options the allowed option short-tags + * @param string $long_options the allowed option long-tags + * @return array the given options and there values + * @access private + */ + function _parseArgs($argv, $short_options, $long_options = null) + { + if (!is_array($argv) && $argv !== null) { + $argv = preg_split('/\s+/', $argv); + } + return Console_Getopt::getopt2($argv, $short_options); + } + + /** + * Output errors with PHP trigger_error(). You can silence the errors + * with prefixing a "@" sign to the function call: @System::mkdir(..); + * + * @param mixed $error a PEAR error or a string with the error message + * @return bool false + * @access private + */ + function raiseError($error) + { + if (PEAR::isError($error)) { + $error = $error->getMessage(); + } + trigger_error($error, E_USER_WARNING); + return false; + } + + /** + * Creates a nested array representing the structure of a directory + * + * System::_dirToStruct('dir1', 0) => + * Array + * ( + * [dirs] => Array + * ( + * [0] => dir1 + * ) + * + * [files] => Array + * ( + * [0] => dir1/file2 + * [1] => dir1/file3 + * ) + * ) + * @param string $sPath Name of the directory + * @param integer $maxinst max. deep of the lookup + * @param integer $aktinst starting deep of the lookup + * @return array the structure of the dir + * @access private + */ + + function _dirToStruct($sPath, $maxinst, $aktinst = 0) + { + $struct = array('dirs' => array(), 'files' => array()); + if (($dir = @opendir($sPath)) === false) { + System::raiseError("Could not open dir $sPath"); + return $struct; // XXX could not open error + } + $struct['dirs'][] = $sPath; // XXX don't add if '.' or '..' ? + $list = array(); + while ($file = readdir($dir)) { + if ($file != '.' && $file != '..') { + $list[] = $file; + } + } + closedir($dir); + sort($list); + if ($aktinst < $maxinst || $maxinst == 0) { + foreach($list as $val) { + $path = $sPath . DIRECTORY_SEPARATOR . $val; + if (is_dir($path)) { + $tmp = System::_dirToStruct($path, $maxinst, $aktinst+1); + $struct = array_merge_recursive($tmp, $struct); + } else { + $struct['files'][] = $path; + } + } + } + return $struct; + } + + /** + * Creates a nested array representing the structure of a directory and files + * + * @param array $files Array listing files and dirs + * @return array + * @see System::_dirToStruct() + */ + function _multipleToStruct($files) + { + $struct = array('dirs' => array(), 'files' => array()); + settype($files, 'array'); + foreach ($files as $file) { + if (is_dir($file)) { + $tmp = System::_dirToStruct($file, 0); + $struct = array_merge_recursive($tmp, $struct); + } else { + $struct['files'][] = $file; + } + } + return $struct; + } + + /** + * The rm command for removing files. + * Supports multiple files and dirs and also recursive deletes + * + * @param string $args the arguments for rm + * @return mixed PEAR_Error or true for success + * @access public + */ + function rm($args) + { + $opts = System::_parseArgs($args, 'rf'); // "f" do nothing but like it :-) + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + foreach($opts[0] as $opt) { + if ($opt[0] == 'r') { + $do_recursive = true; + } + } + $ret = true; + if (isset($do_recursive)) { + $struct = System::_multipleToStruct($opts[1]); + foreach($struct['files'] as $file) { + if (!@unlink($file)) { + $ret = false; + } + } + foreach($struct['dirs'] as $dir) { + if (!@rmdir($dir)) { + $ret = false; + } + } + } else { + foreach ($opts[1] as $file) { + $delete = (is_dir($file)) ? 'rmdir' : 'unlink'; + if (!@$delete($file)) { + $ret = false; + } + } + } + return $ret; + } + + /** + * Make directories. Note that we use call_user_func('mkdir') to avoid + * a problem with ZE2 calling System::mkDir instead of the native PHP func. + * + * @param string $args the name of the director(y|ies) to create + * @return bool True for success + * @access public + */ + function mkDir($args) + { + $opts = System::_parseArgs($args, 'pm:'); + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + $mode = 0777; // default mode + foreach($opts[0] as $opt) { + if ($opt[0] == 'p') { + $create_parents = true; + } elseif($opt[0] == 'm') { + // if the mode is clearly an octal number (starts with 0) + // convert it to decimal + if (strlen($opt[1]) && $opt[1]{0} == '0') { + $opt[1] = octdec($opt[1]); + } else { + // convert to int + $opt[1] += 0; + } + $mode = $opt[1]; + } + } + $ret = true; + if (isset($create_parents)) { + foreach($opts[1] as $dir) { + $dirstack = array(); + while (!@is_dir($dir) && $dir != DIRECTORY_SEPARATOR) { + array_unshift($dirstack, $dir); + $dir = dirname($dir); + } + while ($newdir = array_shift($dirstack)) { + if (!call_user_func('mkdir', $newdir, $mode)) { + $ret = false; + } + } + } + } else { + foreach($opts[1] as $dir) { + if (!@is_dir($dir) && !call_user_func('mkdir', $dir, $mode)) { + $ret = false; + } + } + } + return $ret; + } + + /** + * Concatenate files + * + * Usage: + * 1) $var = System::cat('sample.txt test.txt'); + * 2) System::cat('sample.txt test.txt > final.txt'); + * 3) System::cat('sample.txt test.txt >> final.txt'); + * + * Note: as the class use fopen, urls should work also (test that) + * + * @param string $args the arguments + * @return boolean true on success + * @access public + */ + function &cat($args) + { + $ret = null; + $files = array(); + if (!is_array($args)) { + $args = preg_split('/\s+/', $args); + } + for($i=0; $i < count($args); $i++) { + if ($args[$i] == '>') { + $mode = 'wb'; + $outputfile = $args[$i+1]; + break; + } elseif ($args[$i] == '>>') { + $mode = 'ab+'; + $outputfile = $args[$i+1]; + break; + } else { + $files[] = $args[$i]; + } + } + if (isset($mode)) { + if (!$outputfd = fopen($outputfile, $mode)) { + $err = System::raiseError("Could not open $outputfile"); + return $err; + } + $ret = true; + } + foreach ($files as $file) { + if (!$fd = fopen($file, 'r')) { + System::raiseError("Could not open $file"); + continue; + } + while ($cont = fread($fd, 2048)) { + if (isset($outputfd)) { + fwrite($outputfd, $cont); + } else { + $ret .= $cont; + } + } + fclose($fd); + } + if (@is_resource($outputfd)) { + fclose($outputfd); + } + return $ret; + } + + /** + * Creates temporary files or directories. This function will remove + * the created files when the scripts finish its execution. + * + * Usage: + * 1) $tempfile = System::mktemp("prefix"); + * 2) $tempdir = System::mktemp("-d prefix"); + * 3) $tempfile = System::mktemp(); + * 4) $tempfile = System::mktemp("-t /var/tmp prefix"); + * + * prefix -> The string that will be prepended to the temp name + * (defaults to "tmp"). + * -d -> A temporary dir will be created instead of a file. + * -t -> The target dir where the temporary (file|dir) will be created. If + * this param is missing by default the env vars TMP on Windows or + * TMPDIR in Unix will be used. If these vars are also missing + * c:\windows\temp or /tmp will be used. + * + * @param string $args The arguments + * @return mixed the full path of the created (file|dir) or false + * @see System::tmpdir() + * @access public + */ + function mktemp($args = null) + { + static $first_time = true; + $opts = System::_parseArgs($args, 't:d'); + if (PEAR::isError($opts)) { + return System::raiseError($opts); + } + foreach($opts[0] as $opt) { + if($opt[0] == 'd') { + $tmp_is_dir = true; + } elseif($opt[0] == 't') { + $tmpdir = $opt[1]; + } + } + $prefix = (isset($opts[1][0])) ? $opts[1][0] : 'tmp'; + if (!isset($tmpdir)) { + $tmpdir = System::tmpdir(); + } + if (!System::mkDir("-p $tmpdir")) { + return false; + } + $tmp = tempnam($tmpdir, $prefix); + if (isset($tmp_is_dir)) { + unlink($tmp); // be careful possible race condition here + if (!call_user_func('mkdir', $tmp, 0700)) { + return System::raiseError("Unable to create temporary directory $tmpdir"); + } + } + $GLOBALS['_System_temp_files'][] = $tmp; + if ($first_time) { + PEAR::registerShutdownFunc(array('System', '_removeTmpFiles')); + $first_time = false; + } + return $tmp; + } + + /** + * Remove temporary files created my mkTemp. This function is executed + * at script shutdown time + * + * @access private + */ + function _removeTmpFiles() + { + if (count($GLOBALS['_System_temp_files'])) { + $delete = $GLOBALS['_System_temp_files']; + array_unshift($delete, '-r'); + System::rm($delete); + } + } + + /** + * Get the path of the temporal directory set in the system + * by looking in its environments variables. + * Note: php.ini-recommended removes the "E" from the variables_order setting, + * making unavaible the $_ENV array, that s why we do tests with _ENV + * + * @return string The temporal directory on the system + */ + function tmpdir() + { + if (OS_WINDOWS) { + if ($var = isset($_ENV['TEMP']) ? $_ENV['TEMP'] : getenv('TEMP')) { + return $var; + } + if ($var = isset($_ENV['TMP']) ? $_ENV['TMP'] : getenv('TMP')) { + return $var; + } + if ($var = isset($_ENV['windir']) ? $_ENV['windir'] : getenv('windir')) { + return $var; + } + return getenv('SystemRoot') . '\temp'; + } + if ($var = isset($_ENV['TMPDIR']) ? $_ENV['TMPDIR'] : getenv('TMPDIR')) { + return $var; + } + return '/tmp'; + } + + /** + * The "which" command (show the full path of a command) + * + * @param string $program The command to search for + * @return mixed A string with the full path or false if not found + * @author Stig Bakken + */ + function which($program, $fallback = false) + { + // is_executable() is not available on windows + if (OS_WINDOWS) { + $pear_is_executable = 'is_file'; + } else { + $pear_is_executable = 'is_executable'; + } + + // full path given + if (basename($program) != $program) { + return (@$pear_is_executable($program)) ? $program : $fallback; + } + + // XXX FIXME honor safe mode + $path_delim = OS_WINDOWS ? ';' : ':'; + $exe_suffixes = OS_WINDOWS ? array('.exe','.bat','.cmd','.com') : array(''); + $path_elements = explode($path_delim, getenv('PATH')); + foreach ($exe_suffixes as $suff) { + foreach ($path_elements as $dir) { + $file = $dir . DIRECTORY_SEPARATOR . $program . $suff; + if (@is_file($file) && @$pear_is_executable($file)) { + return $file; + } + } + } + return $fallback; + } + + /** + * The "find" command + * + * Usage: + * + * System::find($dir); + * System::find("$dir -type d"); + * System::find("$dir -type f"); + * System::find("$dir -name *.php"); + * System::find("$dir -name *.php -name *.htm*"); + * System::find("$dir -maxdepth 1"); + * + * Params implmented: + * $dir -> Start the search at this directory + * -type d -> return only directories + * -type f -> return only files + * -maxdepth -> max depth of recursion + * -name -> search pattern (bash style). Multiple -name param allowed + * + * @param mixed Either array or string with the command line + * @return array Array of found files + * + */ + function find($args) + { + if (!is_array($args)) { + $args = preg_split('/\s+/', $args, -1, PREG_SPLIT_NO_EMPTY); + } + $dir = array_shift($args); + $patterns = array(); + $depth = 0; + $do_files = $do_dirs = true; + for ($i = 0; $i < count($args); $i++) { + switch ($args[$i]) { + case '-type': + if (in_array($args[$i+1], array('d', 'f'))) { + if ($args[$i+1] == 'd') { + $do_files = false; + } else { + $do_dirs = false; + } + } + $i++; + break; + case '-name': + $patterns[] = "(" . preg_replace(array('/\./', '/\*/'), + array('\.', '.*'), + $args[$i+1]) + . ")"; + $i++; + break; + case '-maxdepth': + $depth = $args[$i+1]; + break; + } + } + $path = System::_dirToStruct($dir, $depth); + if ($do_files && $do_dirs) { + $files = array_merge($path['files'], $path['dirs']); + } elseif ($do_dirs) { + $files = $path['dirs']; + } else { + $files = $path['files']; + } + if (count($patterns)) { + $patterns = implode('|', $patterns); + $ret = array(); + for ($i = 0; $i < count($files); $i++) { + if (preg_match("#^$patterns\$#", $files[$i])) { + $ret[] = $files[$i]; + } + } + return $ret; + } + return $files; + } +} +?> diff --git a/common/PEAR/XML/Parser.php b/common/PEAR/XML/Parser.php new file mode 100644 index 0000000..6e9c3c9 --- /dev/null +++ b/common/PEAR/XML/Parser.php @@ -0,0 +1,356 @@ + | +// +----------------------------------------------------------------------+ +// +// $Id: Parser.php,v 1.5 2003/02/23 10:48:31 ssb Exp $ + +require_once 'PEAR.php'; + +/** + * XML Parser class. This is an XML parser based on PHP's "xml" extension, + * based on the bundled expat library. + * + * @author Stig Bakken + * @todo Tests that need to be made: + * - error class + * - mixing character encodings + * - a test using all expat handlers + * - options (folding, output charset) + * - different parsing modes + * + * @notes - It requires PHP 4.0.4pl1 or greater + * - From revision 1.17, the function names used by the 'func' mode + * are in the format "xmltag_$elem", for example: use "xmltag_name" + * to handle the tags of your xml file. + */ +class XML_Parser extends PEAR +{ + // {{{ properties + + /** + * @var resource XML parser handle + */ + var $parser; + + /** + * @var resource File handle if parsing from a file + */ + var $fp; + + /** + * @var boolean Whether to do case folding + */ + var $folding = true; + + /** + * @var string Mode of operation, one of "event" or "func" + */ + var $mode; + + /** + * Mapping from expat handler function to class method. + * + * @var array + */ + var $handler = array( + 'character_data_handler' => 'cdataHandler', + 'default_handler' => 'defaultHandler', + 'processing_instruction_handler' => 'piHandler', + 'unparsed_entity_decl_handler' => 'unparsedHandler', + 'notation_decl_handler' => 'notationHandler', + 'external_entity_ref_handler' => 'entityrefHandler' + ); + + /** + * @var string source encoding + */ + var $srcenc; + + /** + * @var string target encoding + */ + var $tgtenc; + + /* + * Use call_user_func when php >= 4.0.7 + * @var boolean + * @see setMode() + */ + var $use_call_user_func = true; + + // }}} + // {{{ constructor + + /** + * Creates an XML parser. + * + * @param string source charset encoding, use NULL (default) to use + * whatever the document specifies + * @param string how this parser object should work, "event" for + * startelement/endelement-type events, "func" + * to have it call functions named after elements + * + * @see xml_parser_create + */ + function XML_Parser($srcenc = null, $mode = "event", $tgtenc = null) + { + $this->PEAR('XML_Parser_Error'); + + if ($srcenc === null) { + $xp = @xml_parser_create(); + } else { + $xp = @xml_parser_create($srcenc); + } + if (is_resource($xp)) { + if ($tgtenc !== null) { + if (!@xml_parser_set_option($xp, XML_OPTION_TARGET_ENCODING, + $tgtenc)) { + return $this->raiseError("invalid target encoding"); + } + } + $this->parser = $xp; + $this->setMode($mode); + xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, $this->folding); + } + $this->srcenc = $srcenc; + $this->tgtenc = $tgtenc; + } + // }}} + + // {{{ setMode() + + /** + * Sets the mode and all handler. + * + * @param string + * @see $handler + */ + function setMode($mode) + { + + $this->mode = $mode; + + xml_set_object($this->parser, $this); + + switch ($mode) { + + case "func": + // use call_user_func() when php >= 4.0.7 + // or call_user_method() if not + if (version_compare(phpversion(), '4.0.7', 'lt')) { + $this->use_call_user_func = false; + } else { + $this->use_call_user_func = true; + } + + xml_set_element_handler($this->parser, "funcStartHandler", "funcEndHandler"); + break; + + case "event": + xml_set_element_handler($this->parser, "startHandler", "endHandler"); + break; + } + + foreach ($this->handler as $xml_func => $method) + if (method_exists($this, $method)) { + $xml_func = "xml_set_" . $xml_func; + $xml_func($this->parser, $method); + } + + } + + // }}} + // {{{ setInputFile() + + /** + * Defines + * + * @param string Filename (full path) + * @return resource fopen handle of the given file + * @throws XML_Parser_Error + * @see setInput(), parse() + * @access public + */ + function setInputFile($file) + { + + $fp = @fopen($file, "rb"); + if (is_resource($fp)) { + $this->fp = $fp; + return $fp; + } + + return $this->raiseError($php_errormsg); + } + + // }}} + // {{{ setInput() + + /** + * Sets the file handle to use with parse(). + * + * @param resource fopen + * @access public + * @see parse(), setInputFile() + */ + function setInput($fp) + { + if (is_resource($fp)) { + $this->fp = $fp; + return true; + } + + return $this->raiseError("not a file resource"); + } + + // }}} + // {{{ parse() + + /** + * Central parsing function. + * + * @throws XML_Parser_Error + * @return boolean true on success + * @see parseString() + * @access public + */ + function parse() + { + if (!is_resource($this->fp)) { + return $this->raiseError("no input"); + } + + while ($data = fread($this->fp, 2048)) { + + $err = $this->parseString($data, feof($this->fp)); + if (PEAR::isError($err)) { + fclose($this->fp); + return $err; + } + + } + + fclose($this->fp); + + return true; + } + + // }}} + // {{{ parseString() + + /** + * Parses a string. + * + * @param string XML data + * @param boolean ??? + * @throws XML_Parser_Error + * @return mixed true on success or a string with the xml parser error + */ + function parseString($data, $eof = false) + { + if (!xml_parse($this->parser, $data, $eof)) { + $err = $this->raiseError($this->parser); + xml_parser_free($this->parser); + return $err; + } + + return true; + } + + // }}} + // {{{ funcStartHandler() + + function funcStartHandler($xp, $elem, $attribs) + { + $func = 'xmltag_' . $elem; + if (method_exists($this, $func)) { + if ($this->use_call_user_func) { + call_user_func(array(&$this, $func), $xp, $elem, $attribs); + } else { + call_user_method($func, $this, $xp, $elem, $attribs); + } + } + + } + + // }}} + // {{{ funcEndHandler() + + function funcEndHandler($xp, $elem) + { + $func = 'xmltag_' . $elem . '_'; + if (method_exists($this, $func)) { + if ($this->use_call_user_func) { + call_user_func(array(&$this, $func), $xp, $elem); + } else { + call_user_method($func, $this, $xp, $elem); + } + } + } + + // }}} + // {{{ startHandler() + + /** + * + * @abstract + */ + function startHandler($xp, $elem, &$attribs) + { + return NULL; + } + + // }}} + // {{{ endHandler() + + /** + * + * @abstract + */ + function endHandler($xp, $elem) + { + return NULL; + } + + + // }}} +} + +class XML_Parser_Error extends PEAR_Error +{ + // {{{ properties + + var $error_message_prefix = 'XML_Parser: '; + + // }}} + // {{{ constructor() + + function XML_Parser_Error($msgorparser = 'unknown error', $code = 0, $mode = PEAR_ERROR_RETURN, $level = E_USER_NOTICE) + { + if (is_resource($msgorparser)) { + $code = xml_get_error_code($msgorparser); + $msgorparser = sprintf("%s at XML input line %d", + xml_error_string($code), + xml_get_current_line_number($msgorparser)); + } + $this->PEAR_Error($msgorparser, $code, $mode, $level); + + } + + // }}} +} +?> \ No newline at end of file diff --git a/common/PEAR/XML/RPC.php b/common/PEAR/XML/RPC.php new file mode 100644 index 0000000..fcf06e2 --- /dev/null +++ b/common/PEAR/XML/RPC.php @@ -0,0 +1,1189 @@ + +// $Id: RPC.php,v 1.21 2004/03/15 13:51:44 pajoye Exp $ + +// License is granted to use or modify this software ("XML-RPC for PHP") +// for commercial or non-commercial use provided the copyright of the author +// is preserved in any distributed or derivative work. + +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Adapted to PEAR standards by Stig S�her Bakken and +// Martin Jansen +// /* $id$ */ + +if (!function_exists('xml_parser_create')) { +// Win 32 fix. From: "Leo West" + if ($WINDIR) { + dl("php_xml.dll"); + } else { + dl("xml.so"); + } +} + +define('XML_RPC_ERROR_INVALID_TYPE', 101); +define('XML_RPC_ERROR_NON_NUMERIC_FOUND', 102); +define('XML_RPC_ERROR_CONNECTION_FAILED', 103); +define('XML_RPC_ERROR_ALREADY_INITIALIZED', 104); + +$GLOBALS['XML_RPC_I4'] = "i4"; +$GLOBALS['XML_RPC_Int'] = "int"; +$GLOBALS['XML_RPC_Boolean'] = "boolean"; +$GLOBALS['XML_RPC_Double'] = "double"; +$GLOBALS['XML_RPC_String'] = "string"; +$GLOBALS['XML_RPC_DateTime'] = "dateTime.iso8601"; +$GLOBALS['XML_RPC_Base64'] = "base64"; +$GLOBALS['XML_RPC_Array'] = "array"; +$GLOBALS['XML_RPC_Struct'] = "struct"; + +$GLOBALS['XML_RPC_Types'] = array($GLOBALS['XML_RPC_I4'] => 1, + $GLOBALS['XML_RPC_Int'] => 1, + $GLOBALS['XML_RPC_Boolean'] => 1, + $GLOBALS['XML_RPC_String'] => 1, + $GLOBALS['XML_RPC_Double'] => 1, + $GLOBALS['XML_RPC_DateTime'] => 1, + $GLOBALS['XML_RPC_Base64'] => 1, + $GLOBALS['XML_RPC_Array'] => 2, + $GLOBALS['XML_RPC_Struct'] => 3); + +$GLOBALS['XML_RPC_entities'] = array("quot" => '"', + "amp" => "&", + "lt" => "<", + "gt" => ">", + "apos" => "'"); + +$GLOBALS['XML_RPC_err']["unknown_method"] = 1; +$GLOBALS['XML_RPC_str']["unknown_method"] = "Unknown method"; +$GLOBALS['XML_RPC_err']["invalid_return"] = 2; +$GLOBALS['XML_RPC_str']["invalid_return"] = "Invalid return payload: enabling debugging to examine incoming payload"; +$GLOBALS['XML_RPC_err']["incorrect_params"] = 3; +$GLOBALS['XML_RPC_str']["incorrect_params"] = "Incorrect parameters passed to method"; +$GLOBALS['XML_RPC_err']["introspect_unknown"] = 4; +$GLOBALS['XML_RPC_str']["introspect_unknown"] = "Can't introspect: method unknown"; +$GLOBALS['XML_RPC_err']["http_error"] = 5; +$GLOBALS['XML_RPC_str']["http_error"] = "Didn't receive 200 OK from remote server."; + +$GLOBALS['XML_RPC_defencoding'] = "UTF-8"; + +// let user errors start at 800 +$GLOBALS['XML_RPC_erruser'] = 800; + +// let XML parse errors start at 100 +$GLOBALS['XML_RPC_errxml'] = 100; + +// formulate backslashes for escaping regexp +$GLOBALS['XML_RPC_backslash'] = chr(92) . chr(92); + +$GLOBALS['XML_RPC_twoslash'] = $GLOBALS['XML_RPC_backslash'] . $GLOBALS['XML_RPC_backslash']; +$GLOBALS['XML_RPC_twoslash'] = "2SLS"; + +// used to store state during parsing +// quick explanation of components: +// st - used to build up a string for evaluation +// ac - used to accumulate values +// qt - used to decide if quotes are needed for evaluation +// cm - used to denote struct or array (comma needed) +// isf - used to indicate a fault +// lv - used to indicate "looking for a value": implements +// the logic to allow values with no types to be strings +// params - used to store parameters in method calls +// method - used to store method name + +$GLOBALS['XML_RPC_xh'] = array(); + +function XML_RPC_entity_decode($string) +{ + $top = split("&", $string); + $op = ""; + $i = 0; + while($i < sizeof($top)) { + if (ereg("^([#a-zA-Z0-9]+);", $top[$i], $regs)) { + $op .= ereg_replace("^[#a-zA-Z0-9]+;", + XML_RPC_lookup_entity($regs[1]), + $top[$i]); + } else { + if ($i == 0) { + $op = $top[$i]; + } else { + $op .= "&" . $top[$i]; + } + } + + $i++; + } + return $op; +} + + +function XML_RPC_lookup_entity($ent) +{ + global $XML_RPC_entities; + + if ($XML_RPC_entities[strtolower($ent)]) { + return $XML_RPC_entities[strtolower($ent)]; + } + + if (ereg("^#([0-9]+)$", $ent, $regs)) { + return chr($regs[1]); + } + + return "?"; +} + + +function XML_RPC_se($parser, $name, $attrs) +{ + global $XML_RPC_xh, $XML_RPC_DateTime, $XML_RPC_String; + + switch ($name) { + case "STRUCT": + case "ARRAY": + $XML_RPC_xh[$parser]['st'] .= "array("; + $XML_RPC_xh[$parser]['cm']++; + // this last line turns quoting off + // this means if we get an empty array we'll + // simply get a bit of whitespace in the eval + $XML_RPC_xh[$parser]['qt'] = 0; + break; + + case "NAME": + $XML_RPC_xh[$parser]['st'] .= "'"; + $XML_RPC_xh[$parser]['ac'] = ""; + break; + + case "FAULT": + $XML_RPC_xh[$parser]['isf'] = 1; + break; + + case "PARAM": + $XML_RPC_xh[$parser]['st'] = ""; + break; + + case "VALUE": + $XML_RPC_xh[$parser]['st'] .= "new XML_RPC_Value("; + $XML_RPC_xh[$parser]['lv'] = 1; + $XML_RPC_xh[$parser]['vt'] = $XML_RPC_String; + $XML_RPC_xh[$parser]['ac'] = ""; + $XML_RPC_xh[$parser]['qt'] = 0; + // look for a value: if this is still 1 by the + // time we reach the first data segment then the type is string + // by implication and we need to add in a quote + break; + + case "I4": + case "INT": + case "STRING": + case "BOOLEAN": + case "DOUBLE": + case "DATETIME.ISO8601": + case "BASE64": + $XML_RPC_xh[$parser]['ac'] = ""; // reset the accumulator + + if ($name == "DATETIME.ISO8601" || $name == "STRING") { + $XML_RPC_xh[$parser]['qt'] = 1; + + if ($name == "DATETIME.ISO8601") { + $XML_RPC_xh[$parser]['vt'] = $XML_RPC_DateTime; + } + + } elseif ($name == "BASE64") { + $XML_RPC_xh[$parser]['qt'] = 2; + } else { + // No quoting is required here -- but + // at the end of the element we must check + // for data format errors. + $XML_RPC_xh[$parser]['qt'] = 0; + } + break; + + case "MEMBER": + $XML_RPC_xh[$parser]['ac'] = ""; + break; + + default: + break; + } + + if ($name!="VALUE") { + $XML_RPC_xh[$parser]['lv'] = 0; + } +} + + +function XML_RPC_ee($parser, $name) +{ + global $XML_RPC_xh,$XML_RPC_Types,$XML_RPC_String; + + switch ($name) { + case "STRUCT": + case "ARRAY": + if ($XML_RPC_xh[$parser]['cm'] && substr($XML_RPC_xh[$parser]['st'], -1) == ',') { + $XML_RPC_xh[$parser]['st'] = substr($XML_RPC_xh[$parser]['st'],0,-1); + } + + $XML_RPC_xh[$parser]['st'] .= ")"; + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + $XML_RPC_xh[$parser]['cm']--; + break; + + case "NAME": + $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac'] . "' => "; + break; + + case "BOOLEAN": + // special case here: we translate boolean 1 or 0 into PHP + // constants true or false + if ($XML_RPC_xh[$parser]['ac'] == '1') { + $XML_RPC_xh[$parser]['ac'] = "true"; + } else { + $XML_RPC_xh[$parser]['ac'] = "false"; + } + + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + // Drop through intentionally. + + case "I4": + case "INT": + case "STRING": + case "DOUBLE": + case "DATETIME.ISO8601": + case "BASE64": + if ($XML_RPC_xh[$parser]['qt'] == 1) { + // we use double quotes rather than single so backslashification works OK + $XML_RPC_xh[$parser]['st'] .= "\"" . $XML_RPC_xh[$parser]['ac'] . "\""; + } elseif ($XML_RPC_xh[$parser]['qt'] == 2) { + $XML_RPC_xh[$parser]['st'] .= "base64_decode('" . $XML_RPC_xh[$parser]['ac'] . "')"; + } elseif ($name=="BOOLEAN") { + $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac']; + } else { + // we have an I4, INT or a DOUBLE + // we must check that only 0123456789-. are characters here + if (!ereg("^\-?[0123456789 \t\.]+$", $XML_RPC_xh[$parser]['ac'])) { + $this->raiseError("Non-numeric value recieved in INT or DOUBLE", XML_RPC_ERROR_NON_NUMERIC_FOUND); + $XML_RPC_xh[$parser]['st'] .= "ERROR_NON_NUMERIC_FOUND"; + } else { + // it's ok, add it on + $XML_RPC_xh[$parser]['st'] .= $XML_RPC_xh[$parser]['ac']; + } + } + + $XML_RPC_xh[$parser]['ac'] = ""; + $XML_RPC_xh[$parser]['qt'] = 0; + $XML_RPC_xh[$parser]['lv'] = 3; // indicate we've found a value + break; + + case "VALUE": + // deal with a string value + if (strlen($XML_RPC_xh[$parser]['ac']) > 0 && + $XML_RPC_xh[$parser]['vt'] == $XML_RPC_String) { + + $XML_RPC_xh[$parser]['st'] .= "\"" . $XML_RPC_xh[$parser]['ac'] . "\""; + } + + // This if () detects if no scalar was inside + // and pads an empty "". + if ($XML_RPC_xh[$parser]['st'][strlen($XML_RPC_xh[$parser]['st'])-1] == '(') { + $XML_RPC_xh[$parser]['st'] .= '""'; + } + $XML_RPC_xh[$parser]['st'] .= ", '" . $XML_RPC_xh[$parser]['vt'] . "')"; + if ($XML_RPC_xh[$parser]['cm']) { + $XML_RPC_xh[$parser]['st'] .= ","; + } + break; + + case "MEMBER": + $XML_RPC_xh[$parser]['ac'] = ""; + $XML_RPC_xh[$parser]['qt'] = 0; + break; + + case "DATA": + $XML_RPC_xh[$parser]['ac'] = ""; + $XML_RPC_xh[$parser]['qt'] = 0; + break; + + case "PARAM": + $XML_RPC_xh[$parser]['params'][] = $XML_RPC_xh[$parser]['st']; + break; + + case "METHODNAME": + $XML_RPC_xh[$parser]['method'] = ereg_replace("^[\n\r\t ]+", "", $XML_RPC_xh[$parser]['ac']); + break; + + case "BOOLEAN": + // special case here: we translate boolean 1 or 0 into PHP + // constants true or false + if ($XML_RPC_xh[$parser]['ac'] == '1') { + $XML_RPC_xh[$parser]['ac'] = "true"; + } else { + $XML_RPC_xh[$parser]['ac'] = "false"; + } + + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + break; + + default: + break; + } + + // if it's a valid type name, set the type + if (isset($XML_RPC_Types[strtolower($name)])) { + $XML_RPC_xh[$parser]['vt'] = strtolower($name); + } +} + + +function XML_RPC_cd($parser, $data) +{ + global $XML_RPC_xh, $XML_RPC_backslash; + + if ($XML_RPC_xh[$parser]['lv'] != 3) { + // "lookforvalue==3" means that we've found an entire value + // and should discard any further character data + + if ($XML_RPC_xh[$parser]['lv'] == 1) { + // if we've found text and we're just in a then + // turn quoting on, as this will be a string + $XML_RPC_xh[$parser]['qt'] = 1; + // and say we've found a value + $XML_RPC_xh[$parser]['lv'] = 2; + } + + // replace characters that eval would + // do special things with + if (isset($XML_RPC_xh[$parser]['ac'])) { + $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$', + str_replace('"', '\"', str_replace(chr(92), + $XML_RPC_backslash, $data))); + } else { + $XML_RPC_xh[$parser]['ac'] = ''; + } + } +} + + +function XML_RPC_dh($parser, $data) +{ + global $XML_RPC_xh; + + if (substr($data, 0, 1) == "&" && substr($data, -1, 1) == ";") { + if ($XML_RPC_xh[$parser]['lv'] == 1) { + $XML_RPC_xh[$parser]['qt'] = 1; + $XML_RPC_xh[$parser]['lv'] = 2; + } + $XML_RPC_xh[$parser]['ac'] .= str_replace('$', '\$', + str_replace('"', '\"', str_replace(chr(92), + $XML_RPC_backslash, $data))); + } +} + +/** + * Base class + * + * This class provides common functions for all of the XML_RPC classes. + */ +class XML_RPC_Base { + function raiseError($msg, $code) + { + include_once 'PEAR.php'; + PEAR::raiseError(get_class($this) . ": " . $msg, $code); + } +} + +class XML_RPC_Client extends XML_RPC_Base { + var $path; + var $server; + var $port; + var $errno; + var $errstring; + var $debug = 0; + var $username = ""; + var $password = ""; + + function XML_RPC_Client($path, $server, $port = 80, + $proxy = '', $proxy_port = 8080, + $proxy_user = '', $proxy_pass = '') + { + $this->port = $port; + $this->server = $server; + $this->path = $path; + $this->proxy = $proxy; + $this->proxy_port = $proxy_port; + $this->proxy_user = $proxy_user; + $this->proxy_pass = $proxy_pass; + } + + function setDebug($in) + { + if ($in) { + $this->debug = 1; + } else { + $this->debug = 0; + } + } + + function setCredentials($u, $p) + { + $this->username = $u; + $this->password = $p; + } + + function send($msg, $timeout = 0) + { + // where msg is an xmlrpcmsg + $msg->debug = $this->debug; + return $this->sendPayloadHTTP10($msg, $this->server, $this->port, + $timeout, $this->username, + $this->password); + } + + function sendPayloadHTTP10($msg, $server, $port, $timeout=0, + $username = "", $password = "") + { + // If we're using a proxy open a socket to the proxy server instead to the xml-rpc server + if ($this->proxy){ + if ($timeout > 0) { + $fp = fsockopen($this->proxy, $this->proxy_port, $this->errno, $this->errstr, $timeout); + } else { + $fp = fsockopen($this->proxy, $this->proxy_port, $this->errno, $this->errstr); + } + } else { + if ($timeout > 0) { + $fp = fsockopen($server, $port, $this->errno, $this->errstr, $timeout); + } else { + $fp = fsockopen($server, $port, $this->errno, $this->errstr); + } + } + + if (!$fp && $this->proxy) { + $this->raiseError( + "Connection to proxy server " . $this->proxy . ":" . $this->proxy_port . " failed", + XML_RPC_ERROR_CONNECTION_FAILED); + } elseif (!$fp) { + $this->raiseError( + "Connection to RPC server " . $this->server . " failed", + XML_RPC_ERROR_CONNECTION_FAILED); + } + + // Only create the payload if it was not created previously + if (empty($msg->payload)) { + $msg->createPayload(); + } + + // thanks to Grant Rauscher for this + $credentials = ""; + if ($username != "") { + $credentials = "Authorization: Basic " . + base64_encode($username . ":" . $password) . "\r\n"; + } + + + if ($this->proxy) { + $op = "POST http://" . $this->server; + + if ($this->proxy_port) { + $op .= ":" . $this->port; + } + } else { + $op = "POST "; + } + + $op .= $this->path. " HTTP/1.0\r\n" . + "User-Agent: PEAR XML_RPC\r\n" . + "Host: " . $this->server . "\r\n"; + if ($this->proxy && $this->proxy_user != '') { + $op .= 'Proxy-Authorization: Basic ' . + base64_encode($this->proxy_user . ':' . $this->proxy_pass) . + "\r\n"; + } + $op .= $credentials . + "Content-Type: text/xml\r\n" . + "Content-Length: " . strlen($msg->payload) . "\r\n\r\n" . + $msg->payload; + + if (!fputs($fp, $op, strlen($op))) { + $this->errstr = "Write error"; + return 0; + } + $resp = $msg->parseResponseFile($fp); + fclose($fp); + return $resp; + } +} + + +class XML_RPC_Response extends XML_RPC_Base +{ + var $xv; + var $fn; + var $fs; + var $hdrs; + + function XML_RPC_Response($val, $fcode = 0, $fstr = "") + { + if ($fcode != 0) { + $this->fn = $fcode; + $this->fs = htmlspecialchars($fstr); + } else { + $this->xv = $val; + } + } + + function faultCode() + { + if (isset($this->fn)) { + return $this->fn; + } else { + return 0; + } + } + + function faultString() + { + return $this->fs; + } + + function value() + { + return $this->xv; + } + + function serialize() + { + $rs = "\n"; + if ($this->fn) { + $rs .= " + + + + faultCode + " . $this->fn . " + + + faultString + " . $this->fs . " + + + +"; + } else { + $rs .= "\n\n" . $this->xv->serialize() . + "\n"; + } + $rs .= "\n"; + return $rs; + } +} + + +class XML_RPC_Message extends XML_RPC_Base +{ + var $payload; + var $methodname; + var $params = array(); + var $debug = 0; + + function XML_RPC_Message($meth, $pars = 0) + { + $this->methodname = $meth; + if (is_array($pars) && sizeof($pars)>0) { + for($i = 0; $i < sizeof($pars); $i++) { + $this->addParam($pars[$i]); + } + } + } + + function xml_header() + { + return "\n\n"; + } + + function xml_footer() + { + return "\n"; + } + + function createPayload() + { + $this->payload = $this->xml_header(); + $this->payload .= "" . $this->methodname . "\n"; + $this->payload .= "\n"; + for($i = 0; $i < sizeof($this->params); $i++) { + $p = $this->params[$i]; + $this->payload .= "\n" . $p->serialize() . "\n"; + } + $this->payload .= "\n"; + $this->payload .= $this->xml_footer(); + $this->payload = str_replace("\n", "\r\n", $this->payload); + } + + function method($meth = "") + { + if ($meth != "") { + $this->methodname = $meth; + } + return $this->methodname; + } + + function serialize() + { + $this->createPayload(); + return $this->payload; + } + + function addParam($par) + { + $this->params[] = $par; + } + + function getParam($i) + { + return $this->params[$i]; + } + + function getNumParams() + { + return sizeof($this->params); + } + + function parseResponseFile($fp) + { + $ipd = ""; + + while($data = fread($fp, 32768)) { + $ipd .= $data; + } + return $this->parseResponse($ipd); + } + + function parseResponse($data = "") + { + global $XML_RPC_xh,$XML_RPC_err,$XML_RPC_str; + global $XML_RPC_defencoding; + + $parser = xml_parser_create($XML_RPC_defencoding); + + $XML_RPC_xh[$parser] = array(); + + $XML_RPC_xh[$parser]['st'] = ""; + $XML_RPC_xh[$parser]['cm'] = 0; + $XML_RPC_xh[$parser]['isf'] = 0; + $XML_RPC_xh[$parser]['ac'] = ""; + $XML_RPC_xh[$parser]['qt'] = ""; + + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser, "XML_RPC_se", "XML_RPC_ee"); + xml_set_character_data_handler($parser, "XML_RPC_cd"); + xml_set_default_handler($parser, "XML_RPC_dh"); + $xmlrpc_value = new XML_RPC_Value; + + $hdrfnd = 0; + if ($this->debug) { + print "
---GOT---\n";
+            print isset($_SERVER['SERVER_PROTOCOL']) ? htmlspecialchars($data) : $data;
+            print "\n---END---\n
"; + } + + // see if we got an HTTP 200 OK, else bomb + // but only do this if we're using the HTTP protocol. + if (ereg("^HTTP",$data) && + !ereg("^HTTP/[0-9\.]+ 200 ", $data)) { + $errstr = substr($data, 0, strpos($data, "\n")-1); + error_log("HTTP error, got response: " . $errstr); + $r = new XML_RPC_Response(0, $XML_RPC_err["http_error"], + $XML_RPC_str["http_error"] . " (" . + $errstr . ")"); + xml_parser_free($parser); + return $r; + } + // gotta get rid of headers here + + + if ((!$hdrfnd) && ($brpos = strpos($data,"\r\n\r\n"))) { + $XML_RPC_xh[$parser]['ha'] = substr($data, 0, $brpos); + $data = substr($data, $brpos + 4); + $hdrfnd = 1; + } + + // be tolerant of junk after methodResponse (e.g. javascript automatically inserted by free hosts) + // thanks to Luca Mariano + $data = substr($data, 0, strpos($data, "") + 17); + + if (!xml_parse($parser, $data, sizeof($data))) { + // thanks to Peter Kocks + if ((xml_get_current_line_number($parser)) == 1) { + $errstr = "XML error at line 1, check URL"; + } else { + $errstr = sprintf("XML error: %s at line %d", + xml_error_string(xml_get_error_code($parser)), + xml_get_current_line_number($parser)); + } + error_log($errstr); + $r = new XML_RPC_Response(0, $XML_RPC_err["invalid_return"], + $XML_RPC_str["invalid_return"]); + xml_parser_free($parser); + return $r; + } + xml_parser_free($parser); + if ($this->debug) { + print "
---EVALING---[" .
+            strlen($XML_RPC_xh[$parser]['st']) . " chars]---\n" .
+            htmlspecialchars($XML_RPC_xh[$parser]['st']) . ";\n---END---
"; + } + if (strlen($XML_RPC_xh[$parser]['st']) == 0) { + // then something odd has happened + // and it's time to generate a client side error + // indicating something odd went on + $r = new XML_RPC_Response(0, $XML_RPC_err["invalid_return"], + $XML_RPC_str["invalid_return"]); + } else { + eval('$v=' . $XML_RPC_xh[$parser]['st'] . '; $allOK=1;'); + if ($XML_RPC_xh[$parser]['isf']) { + $f = $v->structmem("faultCode"); + $fs = $v->structmem("faultString"); + $r = new XML_RPC_Response($v, $f->scalarval(), + $fs->scalarval()); + } else { + $r = new XML_RPC_Response($v); + } + } + $r->hdrs = split("\r?\n", $XML_RPC_xh[$parser]['ha'][1]); + return $r; + } + +} + + +class XML_RPC_Value extends XML_RPC_Base +{ + var $me = array(); + var $mytype = 0; + + function XML_RPC_Value($val = -1, $type = "") + { + global $XML_RPC_Types; + $this->me = array(); + $this->mytype = 0; + if ($val != -1 || $type != "") { + if ($type == "") { + $type="string"; + } + if ($XML_RPC_Types[$type] == 1) { + $this->addScalar($val,$type); + } elseif ($XML_RPC_Types[$type] == 2) { + $this->addArray($val); + } elseif ($XML_RPC_Types[$type] == 3) { + $this->addStruct($val); + } + } + } + + function addScalar($val, $type = "string") + { + global $XML_RPC_Types, $XML_RPC_Boolean; + + if ($this->mytype == 1) { + $this->raiseError("Scalar can have only one value", XML_RPC_ERROR_INVALID_TYPE); + return 0; + } + $typeof = $XML_RPC_Types[$type]; + if ($typeof != 1) { + $this->raiseError("Not a scalar type (${typeof})", XML_RPC_ERROR_INVALID_TYPE); + return 0; + } + + if ($type == $XML_RPC_Boolean) { + if (strcasecmp($val,"true") == 0 || + $val == 1 || + ($val == true && + strcasecmp($val,"false"))) { + + $val = 1; + } else { + $val = 0; + } + } + + if ($this->mytype == 2) { + // we're adding to an array here + $ar = $this->me["array"]; + $ar[] = new XML_RPC_Value($val, $type); + $this->me["array"] = $ar; + } else { + // a scalar, so set the value and remember we're scalar + $this->me[$type] = $val; + $this->mytype = $typeof; + } + return 1; + } + + function addArray($vals) + { + global $XML_RPC_Types; + if ($this->mytype != 0) { + $this->raiseError( + "Already initialized as a [" . $this->kindOf() . "]", + XML_RPC_ERROR_ALREADY_INITIALIZED); + return 0; + } + $this->mytype = $XML_RPC_Types["array"]; + $this->me["array"] = $vals; + return 1; + } + + function addStruct($vals) + { + global $XML_RPC_Types; + if ($this->mytype != 0) { + $this->raiseError( + "Already initialized as a [" . $this->kindOf() . "]", + XML_RPC_ERROR_ALREADY_INITIALIZED); + return 0; + } + $this->mytype = $XML_RPC_Types["struct"]; + $this->me["struct"] = $vals; + return 1; + } + + function dump($ar) + { + reset($ar); + while (list( $key, $val ) = each($ar)) { + echo "$key => $val
"; + if ($key == 'array') { + while ( list( $key2, $val2 ) = each( $val ) ) { + echo "-- $key2 => $val2
"; + } + } + } + } + + function kindOf() + { + switch ($this->mytype) { + case 3: + return "struct"; + break; + case 2: + return "array"; + break; + case 1: + return "scalar"; + break; + default: + return "undef"; + } + } + + function serializedata($typ, $val) + { + $rs = ""; + global $XML_RPC_Types, $XML_RPC_Base64, $XML_RPC_String, $XML_RPC_Boolean; + switch ($XML_RPC_Types[$typ]) { + case 3: + // struct + $rs .= "\n"; + reset($val); + while(list($key2, $val2) = each($val)) { + $rs .= "${key2}\n"; + $rs .= $this->serializeval($val2); + $rs .= "\n"; + } + $rs .= ""; + break; + case 2: + // array + $rs .= "\n\n"; + for($i = 0; $i < sizeof($val); $i++) { + $rs .= $this->serializeval($val[$i]); + } + $rs .= "\n"; + break; + case 1: + switch ($typ) { + case $XML_RPC_Base64: + $rs .= "<${typ}>" . base64_encode($val) . ""; + break; + case $XML_RPC_Boolean: + $rs .= "<${typ}>" . ($val ? "1" : "0") . ""; + break; + case $XML_RPC_String: + $rs .= "<${typ}>" . htmlspecialchars($val). ""; + break; + default: + $rs .= "<${typ}>${val}"; + } + break; + default: + break; + } + return $rs; + } + + function serialize() + { + return $this->serializeval($this); + } + + function serializeval($o) + { + $rs = ""; + $ar = $o->me; + reset($ar); + list($typ, $val) = each($ar); + $rs .= ""; + $rs .= $this->serializedata($typ, $val); + $rs .= "\n"; + return $rs; + } + + function structmem($m) + { + $nv = $this->me["struct"][$m]; + return $nv; + } + + function structreset() + { + reset($this->me["struct"]); + } + + function structeach() + { + return each($this->me["struct"]); + } + + function getval() { + // UNSTABLE + global $XML_RPC_BOOLEAN, $XML_RPC_Base64; + + reset($this->me); + list($a,$b) = each($this->me); + + // contributed by I Sofer, 2001-03-24 + // add support for nested arrays to scalarval + // i've created a new method here, so as to + // preserve back compatibility + + if (is_array($b)) { + foreach ($b as $id => $cont) { + $b[$id] = $cont->scalarval(); + } + } + + // add support for structures directly encoding php objects + if (is_object($b)) { + $t = get_object_vars($b); + foreach ($t as $id => $cont) { + $t[$id] = $cont->scalarval(); + } + foreach ($t as $id => $cont) { + eval('$b->'.$id.' = $cont;'); + } + } + + // end contrib + return $b; + } + + function scalarval() + { + global $XML_RPC_Boolean, $XML_RPC_Base64; + reset($this->me); + list($a,$b) = each($this->me); + return $b; + } + + function scalartyp() + { + global $XML_RPC_I4, $XML_RPC_Int; + reset($this->me); + list($a,$b) = each($this->me); + if ($a == $XML_RPC_I4) { + $a = $XML_RPC_Int; + } + return $a; + } + + function arraymem($m) + { + $nv = $this->me["array"][$m]; + return $nv; + } + + function arraysize() + { + reset($this->me); + list($a,$b) = each($this->me); + return sizeof($b); + } +} + + +/** + * date helpers + */ +function XML_RPC_iso8601_encode($timet, $utc = 0) { + // return an ISO8601 encoded string + // really, timezones ought to be supported + // but the XML-RPC spec says: + // + // "Don't assume a timezone. It should be specified by the server in its + // documentation what assumptions it makes about timezones." + // + // these routines always assume localtime unless + // $utc is set to 1, in which case UTC is assumed + // and an adjustment for locale is made when encoding + if (!$utc) { + $t = strftime("%Y%m%dT%H:%M:%S", $timet); + } else { + if (function_exists("gmstrftime")) { + // gmstrftime doesn't exist in some versions + // of PHP + $t = gmstrftime("%Y%m%dT%H:%M:%S", $timet); + } else { + $t = strftime("%Y%m%dT%H:%M:%S", $timet - date("Z")); + } + } + + return $t; +} + +function XML_RPC_iso8601_decode($idate, $utc = 0) { + // return a timet in the localtime, or UTC + $t = 0; + if (ereg("([0-9]{4})([0-9]{2})([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})", $idate, $regs)) { + + if ($utc) { + $t = gmmktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); + } else { + $t = mktime($regs[4], $regs[5], $regs[6], $regs[2], $regs[3], $regs[1]); + } + } + + return $t; +} + +/** + * Takes a message in PHP XML_RPC object format and translates it into native PHP types. + * + * @author Dan Libby + **/ +function XML_RPC_decode($XML_RPC_val) { + $kind = $XML_RPC_val->kindOf(); + + if ($kind == "scalar") { + return $XML_RPC_val->scalarval(); + + } elseif ($kind == "array") { + $size = $XML_RPC_val->arraysize(); + $arr = array(); + + for($i = 0; $i < $size; $i++) { + $arr[] = XML_RPC_decode($XML_RPC_val->arraymem($i)); + } + return $arr; + + } elseif ($kind == "struct") { + $XML_RPC_val->structreset(); + $arr = array(); + + while(list($key,$value) = $XML_RPC_val->structeach()) { + $arr[$key] = XML_RPC_decode($value); + } + return $arr; + } +} + +/** + * Takes native php types and encodes them into XML_RPC PHP object format. + * + * Feature creep -- could support more types via optional type argument. + * + * @author Dan Libby + **/ +function XML_RPC_encode($php_val) { + global $XML_RPC_Boolean; + global $XML_RPC_Int; + global $XML_RPC_Double; + global $XML_RPC_String; + global $XML_RPC_Array; + global $XML_RPC_Struct; + + $type = gettype($php_val); + $XML_RPC_val = new XML_RPC_Value; + + switch ($type) { + case "array": + $keys = array_keys($php_val); + $count = count($php_val); + $firstkey = $keys[0]; + $lastkey = $keys[$count - 1]; + if ($firstkey === 0 && is_int($lastkey) && ($lastkey + 1) == $count) { + $is_continuous = true; + $expected = 0; + foreach ($keys as $actual) { + if ($actual != $expected) { + $is_continuous = false; + break; + } + $expected++; + } + + if ($is_continuous) { + $arr = array(); + foreach ($php_val as $k => $v) { + $arr[$k] = XML_RPC_encode($v); + } + $XML_RPC_val->addArray($arr); + break; + } + } + // fall though if not numerical and continuous + case "object": + $arr = array(); + foreach ($php_val as $k => $v) { + $arr[$k] = XML_RPC_encode($v); + } + $XML_RPC_val->addStruct($arr); + break; + + case "integer": + $XML_RPC_val->addScalar($php_val, $XML_RPC_Int); + break; + + case "double": + $XML_RPC_val->addScalar($php_val, $XML_RPC_Double); + break; + + case "string": + case "NULL": + $XML_RPC_val->addScalar($php_val, $XML_RPC_String); + break; + + // + // Add support for encoding/decoding of booleans, since they are supported in PHP + case "boolean": + $XML_RPC_val->addScalar($php_val, $XML_RPC_Boolean); + break; + // + + case "unknown type": + default: + $XML_RPC_val = false; + break; + } + return $XML_RPC_val; +} + +?> diff --git a/common/PEAR/XML/RPC/Server.php b/common/PEAR/XML/RPC/Server.php new file mode 100644 index 0000000..729c24e --- /dev/null +++ b/common/PEAR/XML/RPC/Server.php @@ -0,0 +1,310 @@ + + +// License is granted to use or modify this software ("XML-RPC for PHP") +// for commercial or non-commercial use provided the copyright of the author +// is preserved in any distributed or derivative work. + +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Adapted to PEAR standards by Stig S�her Bakken +// /* $Id: Server.php,v 1.6 2004/03/15 13:58:39 pajoye Exp $ */ + +require_once "XML/RPC.php"; + +// listMethods: either a string, or nothing +$GLOBALS['XML_RPC_Server_listMethods_sig'] = + array(array($GLOBALS['XML_RPC_Array'], $GLOBALS['XML_RPC_String']), + array($GLOBALS['XML_RPC_Array'])); +$GLOBALS['XML_RPC_Server_listMethods_doc'] = + 'This method lists all the methods that the XML-RPC server knows how to dispatch'; + +function XML_RPC_Server_listMethods($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + $v = new XML_RPC_Value(); + $dmap = $server->dmap; + $outAr = array(); + for (reset($dmap); list($key, $val) = each($dmap); ) { + $outAr[] = new XML_RPC_Value($key, "string"); + } + $dmap = $XML_RPC_Server_dmap; + for (reset($dmap); list($key, $val) = each($dmap); ) { + $outAr[] = new XML_RPC_Value($key, "string"); + } + $v->addArray($outAr); + return new XML_RPC_Response($v); +} + +$GLOBALS['XML_RPC_Server_methodSignature_sig'] = + array(array($GLOBALS['XML_RPC_Array'], $GLOBALS['XML_RPC_String'])); +$GLOBALS['XML_RPC_Server_methodSignature_doc'] = + 'Returns an array of known signatures (an array of arrays) for the method name passed. If no signatures are known, returns a none-array (test for type != array to detect missing signature)'; + +function XML_RPC_Server_methodSignature($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $methName = $m->getParam(0); + $methName = $methName->scalarval(); + if (ereg("^system\.", $methName)) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $server->dmap; + $sysCall = 0; + } + // print "\n"; + if (isset($dmap[$methName])) { + if ($dmap[$methName]["signature"]) { + $sigs = array(); + $thesigs = $dmap[$methName]["signature"]; + for ($i = 0; $i < sizeof($thesigs); $i++) { + $cursig = array(); + $inSig = $thesigs[$i]; + for ($j = 0; $j < sizeof($inSig); $j++) { + $cursig[] = new XML_RPC_Value($inSig[$j], "string"); + } + $sigs[] = new XML_RPC_Value($cursig, "array"); + } + $r = new XML_RPC_Response(new XML_RPC_Value($sigs, "array")); + } else { + $r = new XML_RPC_Response(new XML_RPC_Value("undef", "string")); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err["introspect_unknown"], + $XML_RPC_str["introspect_unknown"]); + } + return $r; +} + +$GLOBALS['XML_RPC_Server_methodHelp_sig'] = + array(array($GLOBALS['XML_RPC_String'], $GLOBALS['XML_RPC_String'])); +$GLOBALS['XML_RPC_Server_methodHelp_doc'] = + 'Returns help text if defined for the method passed, otherwise returns an empty string'; + +function XML_RPC_Server_methodHelp($server, $m) +{ + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_Server_dmap; + + $methName = $m->getParam(0); + $methName = $methName->scalarval(); + if (ereg("^system\.", $methName)) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $server->dmap; + $sysCall = 0; + } + // print "\n"; + if (isset($dmap[$methName])) { + if ($dmap[$methName]["docstring"]) { + $r = new XML_RPC_Response(new XML_RPC_Value($dmap[$methName]["docstring"]), "string"); + } else { + $r = new XML_RPC_Response(new XML_RPC_Value("", "string")); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err["introspect_unknown"], + $XML_RPC_str["introspect_unknown"]); + } + return $r; +} + +$GLOBALS['XML_RPC_Server_dmap'] = array( + "system.listMethods" => + array("function" => "XML_RPC_Server_listMethods", + "signature" => $GLOBALS['XML_RPC_Server_listMethods_sig'], + "docstring" => $GLOBALS['XML_RPC_Server_listMethods_doc']), + + "system.methodHelp" => + array("function" => "XML_RPC_Server_methodHelp", + "signature" => $GLOBALS['XML_RPC_Server_methodHelp_sig'], + "docstring" => $GLOBALS['XML_RPC_Server_methodHelp_doc']), + + "system.methodSignature" => + array("function" => "XML_RPC_Server_methodSignature", + "signature" => $GLOBALS['XML_RPC_Server_methodSignature_sig'], + "docstring" => $GLOBALS['XML_RPC_Server_methodSignature_doc']) +); + +$GLOBALS['XML_RPC_Server_debuginfo'] = ""; + +function XML_RPC_Server_debugmsg($m) +{ + global $XML_RPC_Server_debuginfo; + $XML_RPC_Server_debuginfo = $XML_RPC_Server_debuginfo . $m . "\n"; +} + +class XML_RPC_Server +{ + var $dmap = array(); + + function XML_RPC_Server($dispMap, $serviceNow = 1) + { + global $HTTP_RAW_POST_DATA; + // dispMap is a despatch array of methods + // mapped to function names and signatures + // if a method + // doesn't appear in the map then an unknown + // method error is generated + $this->dmap = $dispMap; + if ($serviceNow) { + $this->service(); + } + } + + function serializeDebug() + { + global $XML_RPC_Server_debuginfo; + if ($XML_RPC_Server_debuginfo != "") + return "\n"; + else + return ""; + } + + function service() + { + $r = $this->parseRequest(); + $payload = "\n" . + $this->serializeDebug() . + $r->serialize(); + header('Content-Length: ' . strlen($payload)); + header('Content-Type: text/xml'); + print $payload; + } + + function verifySignature($in, $sig) + { + for ($i = 0; $i < sizeof($sig); $i++) { + // check each possible signature in turn + $cursig = $sig[$i]; + if (sizeof($cursig) == $in->getNumParams() + 1) { + $itsOK = 1; + for ($n = 0; $n < $in->getNumParams(); $n++) { + $p = $in->getParam($n); + // print "\n"; + if ($p->kindOf() == "scalar") { + $pt = $p->scalartyp(); + } else { + $pt = $p->kindOf(); + } + // $n+1 as first type of sig is return type + if ($pt != $cursig[$n+1]) { + $itsOK = 0; + $pno = $n+1; + $wanted = $cursig[$n+1]; + $got = $pt; + break; + } + } + if ($itsOK) + return array(1); + } + } + return array(0, "Wanted ${wanted}, got ${got} at param ${pno})"); + } + + function parseRequest($data = "") + { + global $XML_RPC_xh,$HTTP_RAW_POST_DATA; + global $XML_RPC_err, $XML_RPC_str, $XML_RPC_errxml, + $XML_RPC_defencoding, $XML_RPC_Server_dmap; + + if ($data == "") { + $data = $HTTP_RAW_POST_DATA; + } + $parser = xml_parser_create($XML_RPC_defencoding); + + $XML_RPC_xh[$parser] = array(); + $XML_RPC_xh[$parser]['st'] = ""; + $XML_RPC_xh[$parser]['cm'] = 0; + $XML_RPC_xh[$parser]['isf'] = 0; + $XML_RPC_xh[$parser]['params'] = array(); + $XML_RPC_xh[$parser]['method'] = ""; + + $plist = ''; + + // decompose incoming XML into request structure + + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, true); + xml_set_element_handler($parser, "XML_RPC_se", "XML_RPC_ee"); + xml_set_character_data_handler($parser, "XML_RPC_cd"); + xml_set_default_handler($parser, "XML_RPC_dh"); + if (!xml_parse($parser, $data, 1)) { + // return XML error as a faultCode + $r = new XML_RPC_Response(0, + $XML_RPC_errxml+xml_get_error_code($parser), + sprintf("XML error: %s at line %d", + xml_error_string(xml_get_error_code($parser)), + xml_get_current_line_number($parser))); + xml_parser_free($parser); + } else { + xml_parser_free($parser); + $m = new XML_RPC_Message($XML_RPC_xh[$parser]['method']); + // now add parameters in + for ($i = 0; $i < sizeof($XML_RPC_xh[$parser]['params']); $i++) { + // print "\n"; + $plist .= "$i - " . $XML_RPC_xh[$parser]['params'][$i] . " \n"; + eval('$m->addParam(' . $XML_RPC_xh[$parser]['params'][$i] . ");"); + } + XML_RPC_Server_debugmsg($plist); + // now to deal with the method + $methName = $XML_RPC_xh[$parser]['method']; + if (ereg("^system\.", $methName)) { + $dmap = $XML_RPC_Server_dmap; + $sysCall = 1; + } else { + $dmap = $this->dmap; + $sysCall = 0; + } + if (isset($dmap[$methName]['function'])) { + // dispatch if exists + if (isset($dmap[$methName]['signature'])) { + $sr = $this->verifySignature($m, + $dmap[$methName]['signature'] ); + } + if ( (!isset($dmap[$methName]['signature'])) || $sr[0]) { + // if no signature or correct signature + if ($sysCall) { + eval('$r=' . $dmap[$methName]['function'] . '($this, $m);'); + } else { + eval('$r=' . $dmap[$methName]['function'] . '($m);'); + } + } else { + $r = new XML_RPC_Response(0, $XML_RPC_err["incorrect_params"], + $XML_RPC_str["incorrect_params"] . + ": " . $sr[1]); + } + } else { + // else prepare error response + $r = new XML_RPC_Response(0, $XML_RPC_err["unknown_method"], + $XML_RPC_str["unknown_method"]); + } + } + return $r; + } + + function echoInput() { + global $HTTP_RAW_POST_DATA; + + // a debugging routine: just echos back the input + // packet as a string value + + $r = new XML_RPC_Response; + $r->xv = new XML_RPC_Value("'Aha said I: '" . $HTTP_RAW_POST_DATA, "string"); + print $r->serialize(); + } +} + +?> diff --git a/common/PEAR/data/PEAR/package.dtd b/common/PEAR/data/PEAR/package.dtd new file mode 100644 index 0000000..8938d08 --- /dev/null +++ b/common/PEAR/data/PEAR/package.dtd @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/common/PEAR/data/PEAR/template.spec b/common/PEAR/data/PEAR/template.spec new file mode 100644 index 0000000..8ab291c --- /dev/null +++ b/common/PEAR/data/PEAR/template.spec @@ -0,0 +1,64 @@ +Summary: PEAR: @summary@ +Name: @rpm_package@ +Version: @version@ +Release: 1 +License: @release_license@ +Group: Development/Libraries +Source: http://@master_server@/get/@package@-%{version}.tgz +BuildRoot: %{_tmppath}/%{name}-root +URL: http://@master_server@/ +Prefix: %{_prefix} +#Docdir: @doc_dir@/@package@ +BuildArchitectures: @arch@ +@extra_headers@ + +%description +@description@ + +%prep +rm -rf %{buildroot}/* +# XXX Source files location is missing here in pear cmd +pear -v -c %{buildroot}/pearrc \ + -d php_dir=%{_libdir}/php/pear \ + -d doc_dir=/docs \ + -d bin_dir=%{_bindir} \ + -d data_dir=%{_libdir}/php/pear/data \ + -d test_dir=%{_libdir}/php/pear/tests \ + -d ext_dir=%{_libdir} \ + -s + +%build +echo BuildRoot=%{buildroot} + +%postun +pear uninstall --nodeps -r @package@ +rm @rpm_xml_dir@/@package@.xml + +%post +pear install --nodeps -r @rpm_xml_dir@/@package@.xml + +%install +pear -c %{buildroot}/pearrc install --nodeps -R %{buildroot} \ + $RPM_SOURCE_DIR/@package@-%{version}.tgz +rm %{buildroot}/pearrc +rm %{buildroot}/%{_libdir}/php/pear/.filemap +rm %{buildroot}/%{_libdir}/php/pear/.lock +rm -rf %{buildroot}/%{_libdir}/php/pear/.registry +if [ -d "%{buildroot}/docs/@package@/doc" ]; then + rm -rf $RPM_BUILD_DIR/doc + mv %{buildroot}/docs/@package@/doc $RPM_BUILD_DIR + rm -rf %{buildroot}/docs +fi +mkdir -p %{buildroot}@rpm_xml_dir@ +tar -xzf $RPM_SOURCE_DIR/@package@-%{version}.tgz package.xml +cp -p package.xml %{buildroot}@rpm_xml_dir@/@package@.xml + +#rm -rf %{buildroot}/* +#pear -q install -R %{buildroot} -n package.xml +#mkdir -p %{buildroot}@rpm_xml_dir@ +#cp -p package.xml %{buildroot}@rpm_xml_dir@/@package@.xml + +%files + %defattr(-,root,root) + %doc @doc_files@ + / diff --git a/common/PEAR/pearcmd.php b/common/PEAR/pearcmd.php new file mode 100644 index 0000000..e91ec82 --- /dev/null +++ b/common/PEAR/pearcmd.php @@ -0,0 +1,311 @@ + | +// | Tomas V.V.Cox | +// | | +// +----------------------------------------------------------------------+ +// +// $Id: pearcmd.php,v 1.1.2.13 2004/06/08 17:56:45 cellog Exp $ + +ob_end_clean(); +/** + * @nodep Gtk + */ +if ('/usr/local/php/lib/php' != '@'.'include_path'.'@') { + ini_set('include_path', '/usr/local/php/lib/php'); +} +ini_set('allow_url_fopen', true); +if (!ini_get('safe_mode')) { + set_time_limit(0); +} +ob_implicit_flush(true); +ini_set('track_errors', true); +ini_set('html_errors', false); +ini_set('magic_quotes_runtime', false); +set_error_handler('error_handler'); + +$pear_package_version = "1.3.2"; + +require_once 'PEAR.php'; +require_once 'PEAR/Config.php'; +require_once 'PEAR/Command.php'; +require_once 'Console/Getopt.php'; + +PEAR_Command::setFrontendType('CLI'); +$all_commands = PEAR_Command::getCommands(); + +$argv = Console_Getopt::readPHPArgv(); +/* $progname = basename($argv[0]); */ +$progname = 'pear'; +if (in_array('getopt2', get_class_methods('Console_Getopt'))) { + array_shift($argv); + $options = Console_Getopt::getopt2($argv, "c:C:d:D:Gh?sSqu:vV"); +} else { + $options = Console_Getopt::getopt($argv, "c:C:d:D:Gh?sSqu:vV"); +} +if (PEAR::isError($options)) { + usage($options); +} + +$opts = $options[0]; + +$fetype = 'CLI'; +if ($progname == 'gpear' || $progname == 'pear-gtk') { + $fetype = 'Gtk'; +} else { + foreach ($opts as $opt) { + if ($opt[0] == 'G') { + $fetype = 'Gtk'; + } + } +} +PEAR_Command::setFrontendType($fetype); +$ui = &PEAR_Command::getFrontendObject(); +PEAR::setErrorHandling(PEAR_ERROR_CALLBACK, array($ui, "displayFatalError")); + +$pear_user_config = ''; +$pear_system_config = ''; +$store_user_config = false; +$store_system_config = false; +$verbose = 1; + +foreach ($opts as $opt) { + switch ($opt[0]) { + case 'c': + $pear_user_config = $opt[1]; + break; + case 'C': + $pear_system_config = $opt[1]; + break; + } +} + +$config = &PEAR_Config::singleton($pear_user_config, $pear_system_config); +$verbose = $config->get("verbose"); +$cmdopts = array(); + +foreach ($opts as $opt) { + $param = !empty($opt[1]) ? $opt[1] : true; + switch ($opt[0]) { + case 'd': + list($key, $value) = explode('=', $param); + $config->set($key, $value, 'user'); + break; + case 'D': + list($key, $value) = explode('=', $param); + $config->set($key, $value, 'system'); + break; + case 's': + $store_user_config = true; + break; + case 'S': + $store_system_config = true; + break; + case 'u': + $config->remove($param, 'user'); + break; + case 'v': + $config->set('verbose', $config->get('verbose') + 1); + break; + case 'q': + $config->set('verbose', $config->get('verbose') - 1); + break; + case 'V': + usage(null, 'version'); + default: + // all non pear params goes to the command + $cmdopts[$opt[0]] = $param; + break; + } +} + +if ($store_system_config) { + $config->store('system'); +} + +if ($store_user_config) { + $config->store('user'); +} + +$command = (isset($options[1][0])) ? $options[1][0] : null; + +if (empty($command) && ($store_user_config || $store_system_config)) { + exit; +} + +if ($fetype == 'Gtk') { + Gtk::main(); +} else do { + if ($command == 'help') { + usage(null, @$options[1][1]); + } + + PEAR::pushErrorHandling(PEAR_ERROR_RETURN); + $cmd = PEAR_Command::factory($command, $config); + PEAR::popErrorHandling(); + if (PEAR::isError($cmd)) { + usage(null, @$options[1][1]); + } + + $short_args = $long_args = null; + PEAR_Command::getGetoptArgs($command, $short_args, $long_args); + if (in_array('getopt2', get_class_methods('Console_Getopt'))) { + array_shift($options[1]); + $tmp = Console_Getopt::getopt2($options[1], $short_args, $long_args); + } else { + $tmp = Console_Getopt::getopt($options[1], $short_args, $long_args); + } + if (PEAR::isError($tmp)) { + break; + } + list($tmpopt, $params) = $tmp; + $opts = array(); + foreach ($tmpopt as $foo => $tmp2) { + list($opt, $value) = $tmp2; + if ($value === null) { + $value = true; // options without args + } + if (strlen($opt) == 1) { + $cmdoptions = $cmd->getOptions($command); + foreach ($cmdoptions as $o => $d) { + if (@$d['shortopt'] == $opt) { + $opts[$o] = $value; + } + } + } else { + if (substr($opt, 0, 2) == '--') { + $opts[substr($opt, 2)] = $value; + } + } + } + $ok = $cmd->run($command, $opts, $params); + if ($ok === false) { + PEAR::raiseError("unknown command `$command'"); + } +} while (false); + +// {{{ usage() + +function usage($error = null, $helpsubject = null) +{ + global $progname, $all_commands; + $stderr = fopen('php://stderr', 'w'); + if (PEAR::isError($error)) { + fputs($stderr, $error->getMessage() . "\n"); + } elseif ($error !== null) { + fputs($stderr, "$error\n"); + } + if ($helpsubject != null) { + $put = cmdHelp($helpsubject); + } else { + $put = + "Usage: $progname [options] command [command-options] \n". + "Type \"$progname help options\" to list all options.\n". + "Type \"$progname help \" to get the help for the specified command.\n". + "Commands:\n"; + $maxlen = max(array_map("strlen", $all_commands)); + $formatstr = "%-{$maxlen}s %s\n"; + ksort($all_commands); + foreach ($all_commands as $cmd => $class) { + $put .= sprintf($formatstr, $cmd, PEAR_Command::getDescription($cmd)); + } + } + fputs($stderr, "$put\n"); + fclose($stderr); + exit; +} + +function cmdHelp($command) +{ + global $progname, $all_commands, $config; + if ($command == "options") { + return + "Options:\n". + " -v increase verbosity level (default 1)\n". + " -q be quiet, decrease verbosity level\n". + " -c file find user configuration in `file'\n". + " -C file find system configuration in `file'\n". + " -d foo=bar set user config variable `foo' to `bar'\n". + " -D foo=bar set system config variable `foo' to `bar'\n". + " -G start in graphical (Gtk) mode\n". + " -s store user configuration\n". + " -S store system configuration\n". + " -u foo unset `foo' in the user configuration\n". + " -h, -? display help/usage (this message)\n". + " -V version information\n"; + } elseif ($command == "shortcuts") { + $sc = PEAR_Command::getShortcuts(); + $ret = "Shortcuts:\n"; + foreach ($sc as $s => $c) { + $ret .= sprintf(" %-8s %s\n", $s, $c); + } + return $ret; + + } elseif ($command == "version") { + return "PEAR Version: ".$GLOBALS['pear_package_version']. + "\nPHP Version: ".phpversion(). + "\nZend Engine Version: ".zend_version(). + "\nRunning on: ".php_uname(); + + } elseif ($help = PEAR_Command::getHelp($command)) { + if (is_string($help)) { + return "$progname $command [options] $help\n"; + } + if ($help[1] === null) { + return "$progname $command $help[0]"; + } else { + return "$progname $command [options] $help[0]\n$help[1]"; + } + } + return "Command '$command' is not valid, try 'pear help'"; +} + +// }}} + +function error_handler($errno, $errmsg, $file, $line, $vars) { + if ((defined('E_STRICT') && $errno & E_STRICT) || !error_reporting()) { + return; // @silenced error + } + $errortype = array ( + E_ERROR => "Error", + E_WARNING => "Warning", + E_PARSE => "Parsing Error", + E_NOTICE => "Notice", + E_CORE_ERROR => "Core Error", + E_CORE_WARNING => "Core Warning", + E_COMPILE_ERROR => "Compile Error", + E_COMPILE_WARNING => "Compile Warning", + E_USER_ERROR => "User Error", + E_USER_WARNING => "User Warning", + E_USER_NOTICE => "User Notice" + ); + $prefix = $errortype[$errno]; + $file = basename($file); + print "\n$prefix: $errmsg in $file on line $line\n"; +} + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: nil + * mode: php + * End: + */ +// vim600:syn=php + +?> diff --git a/common/common.php b/common/common.php new file mode 100644 index 0000000..0fa1774 --- /dev/null +++ b/common/common.php @@ -0,0 +1,249 @@ +disconnect(); + + ### unset + unset($_DB); + } + + if(_ALERT == "1"){ + return _MSG; + }else{ + //return ob_gzhandler($buffer,5); + return $buffer; + } + // 모든 apples를 oranges로 치환합니다. + //return (str_replace("apples", "oranges", $buffer)); + } + + ob_start("callback"); //출력 버퍼링을 켭니다. 출력 버퍼링을 활성화하면, (헤더를 제외한) 스크립트의 모든 출력을 내부 버퍼에 저장하고, 실제로 전송하지 않습니다. + + # for HTTP/1.1 + header ('Cache-Control: no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0'); + # for HTTP/1.0 + header ('Pragma: no-cache'); + + require_once dirname(__file__).'/conf/config.php'; // 기본설정 + require_once dirname(__file__).'/lib/lib.util.php'; // 함수 + require_once dirname(__file__).'/lib/class.cipher.php'; // 암호화/복호화 + require_once dirname(__file__).'/phpThumb/phpThumb.config.php'; //썸네일 + require_once dirname(__file__).'/upload/src/class.upload.php'; //썸네일 변환 + require_once dirname(__file__).'/lib/class.smtp.php'; // SMTP + require_once dirname(__file__).'/lib/class.phpmailer.php'; // SMTP + require_once dirname(__file__).'/lib/class.user.php'; // 회원 + require_once dirname(__file__).'/lib/class.board.php'; // 게시판 + require_once dirname(__file__).'/lib/class.contact.php'; // 문의 + require_once dirname(__file__).'/lib/class.popup.php'; // 팝업 + require_once dirname(__file__).'/lib/class.banner.php'; // 배너관리 + require_once dirname(__file__).'/lib/class.history.php'; // 연혁관리 + + $sessdir = str_replace("/mobile","",_PDS)."sessions"; + ini_set('session.save_path', $sessdir); + + ### 정보에 대해 세션을 사용할것이다. 따라서 이곳에서 start 해준다. + if(!session_id()){ + session_start(); + } + + // 1 시간 이상된 세션을 강제로 삭제한다. + $d = dir(_PDS."sessions"); + while (false !== ($entry = $d->read())) { + if (substr($entry, 0, 1) != '.' && $entry != 'index.php'){ + $temp = file(_PDS."sessions" . '/' . $entry); + if( date ("YmdHis", filemtime(_PDS."sessions" . '/' . $entry)) < date("YmdHis",strtotime("-1 hour", strtotime(date ("Y-m-d H:i:s")))) ){ + @unlink(_PDS."sessions" . '/' . $entry); + + } + //debug($temp); + } + } + + // pear 패키지가 기본만 설치되어 있어 더 필요한 부분을 사용할때 이용하기 위한 부분이다. + ini_set ("include_path",dirname(__file__)."/PEAR/".PATH_SEPARATOR.dirname(__file__)."/lib/".PATH_SEPARATOR.ini_get("include_path")); + + // 0 이면 디버그 메세지 출력 안함, 1일경우 디버깅 메세지 출력 + $_DEBUG = 1; + + require_once "DB.php"; + + ### DB connect + $res = $_DB = DB::connect(_DSN); + if(DB::isError($res)){die($res->getMessage());} + + $res = $_DB->query(" SET NAMES 'utf8' COLLATE 'utf8_general_ci' "); + if (DB::isError($res)) die($res->getMessage()); + + $res = $_DB->query(" SET CHARACTER SET utf8 "); + if (DB::isError($res)) die($res->getMessage()); + + $res = $_DB->query(" set character_set_server = 'utf8' "); + if (DB::isError($res)) die($res->getMessage()); + + $res = $_DB->query(" set character_set_client = 'utf8' "); + if (DB::isError($res)) die($res->getMessage()); + + $res = $_DB->query(" set character_set_results = 'utf8' "); + if (DB::isError($res)) die($res->getMessage()); + + $res = $_DB->query(" set character_set_connection = 'utf8' "); + if (DB::isError($res)) die($res->getMessage()); + + + // 기본 Object 선언 + $obj_User = new User($_DB); // 회원 class + $Obj_board = new Board($_DB); // 게시판 class + $Obj_contact = new Contact($_DB); // 문의 class + $Obj_popup = new Popup($_DB); // 팝업 class + $Obj_banner = new Banner($_DB);// 배너관리 class + $Obj_history = new History($_DB); // 회사연혁 class + + // 설정 Object 선언 + + $user_info = $obj_User->get_status(); + + $query = " + select + * + from + basic + "; + $res = $_basic = $_DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("","서버 오류입니다.\\n[".$res->getMessage()."]"); + exit; + } + + define("_TITLE", $_basic['b_title']); # 타이틀바 + define("_TITLE_EN", $_basic['b_title_en']); # 타이틀바 + define("_DOCTYPE", $_basic['b_doctype']); # DOCTYPE + define("_CHARSET", $_basic['b_charset']); # charset + define("_MASTER_NAME", $_basic['b_title']); # 메일 발송자 + define("_MASTER_EMAIL", $_basic['b_email']); # 대표이메일 + define("_MASTER_EMAIL_BUSINESS", $_basic['b_email_business']); # 사업제휴 + define("_MASTER_EMAIL_PRODUCT", $_basic['b_email_product']); # 제품문의 + define("_MASTER_COMPANY", $_basic['b_company']); # 회사명 + define("_MASTER_EMAIL_BRANCH", $_basic['b_email_branch']); # 지사 대표이메일 + define("_MASTER_TEL", $_basic['b_tel']); # 대표 연락처 + define("_MASTER_TEL_EN", $_basic['b_tel_en']); # 대표 연락처 + define("_MASTER_TEL_BRANCH", $_basic['b_tel_branch']); # 지사 대표 연락처 + define("_MASTER_TEL_BRANCH_EN", $_basic['b_tel_branch_en']); # 지사 대표 연락처 + define("_MASTER_FAX", $_basic['b_fax']); # 대표 fax + define("_MASTER_FAX_EN", $_basic['b_fax_en']); # 대표 fax + define("_MASTER_FAX_BRANCH", $_basic['b_fax_branch']); # 지사 대표 fax + define("_MASTER_FAX_BRANCH_EN", $_basic['b_fax_branch_en']); # 지사 대표 fax + define("_MASTER_ADDR", $_basic['b_addr']); # 주소 + define("_MASTER_ADDR_EN", $_basic['b_addr_en']); # 주소 + define("_MASTER_ADDR_BRANCH", $_basic['b_addr_branch']); # 지사 주소 + define("_MASTER_ADDR_BRANCH_EN", $_basic['b_addr_branch_en']); # 지사 주소 + define("_MASTER_CRN", $_basic['b_crn']); # 사업자등록번호 + define("_MASTER_PRESIDENT", $_basic['b_president']); # 대표이사 + define("_MASTER_PRESIDENT_EN", $_basic['b_president_en']); # 대표이사 + define("_DESCRIPTION", $_basic['b_description']); # DESCRIPTION + define("_DESCRIPTION_EN", $_basic['b_description_en']); # DESCRIPTION + + # 문자왕국 설정값 + $_SMS_ID = $_basic['b_sms_id']; + $_SMS_PW = $_basic['b_sms_pw']; + $_SMS_SENDER = $_basic['b_sms_sender']; + $_SMS_RECEIVERS = $_basic['b_sms_receivers']; + define("_SMS_ID", $_SMS_ID); + define("_SMS_PW", $_SMS_PW); + define("_SMS_SENDER", $_SMS_SENDER); + define("_SMS_RECEIVERS", $_SMS_RECEIVERS); + + # SMTP 계정 + $_b_smtp_host = explode("@",$_basic['b_smtp_id']); + $_SMTP_MAIL_HOST = "smtp.".$_b_smtp_host[1]; + $_SMTP_MAIL_ID = $_basic['b_smtp_id']; + $_SMTP_MAIL_PW = $_basic['b_smtp_pwd']; + define("_SMTP_MAIL_HOST", $_SMTP_MAIL_HOST); + define("_SMTP_MAIL_ID", $_SMTP_MAIL_ID); + define("_SMTP_MAIL_PW", $_SMTP_MAIL_PW); + + # 구글 리캡차 + $_Site_Key = $_basic['google_Site_Key']; + $_Secret_Key = $_basic['google_Secret_Key']; + define("_SITE_KEY", $_Site_Key); + define("_SECRET_KEY", $_Secret_Key); + + + // 모든 변수 담기 + if (isset ($_GET) && get_magic_quotes_gpc ()) array_walk ($_GET, "StripAllSlashes"); + if (isset ($_POST) && get_magic_quotes_gpc ()) array_walk ($_POST, "StripAllSlashes"); + $argu = array_merge($_GET, $_POST); + array_walk($argu, "trimvalues"); + + //모바일 체크 + $chk_m = rtn_mobile_chk(); + +// LANGAUAGE + header('P3P: CP="NOI CURa ADMa DEVa TAIa OUR DELa BUS IND PHY ONL UNI COM NAV INT DEM PRE"'); + + header('Cache-control: private'); // IE 6 FIX + + if(isSet($_GET['lang'])) + { + $language = $_GET['lang']; + + // register the session and set the cookie + $_COOKIE['lang'] = $language; + + setcookie("lang", $language, time() + (3600 * 24 * 30)); + } + else if(isSet($_COOKIE['lang'])) + { + $language = $_COOKIE['lang']; + } + else if(isSet($_COOKIE['lang'])) + { + $language = $_COOKIE['lang']; + } + else + { + $language = 'ko'; + } + + + switch ($language) { + case 'ko': + $language_file = 'lang.ko.php'; + $_DESCRIPTION = _DESCRIPTION; + $_MASTER_TEL = _MASTER_TEL; + $_MASTER_FAX = _MASTER_FAX; + $_MASTER_ADDR = _MASTER_ADDR; + break; + + case 'en': + $language_file = 'lang.en.php'; + $_DESCRIPTION = _DESCRIPTION_EN; + $_MASTER_TEL = _MASTER_TEL_EN; + $_MASTER_FAX = _MASTER_FAX_EN; + $_MASTER_ADDR = _MASTER_ADDR_EN; + break; + + default: + $language_file = 'lang.ko.php'; + $_DESCRIPTION = _DESCRIPTION; + $_MASTER_TEL = _MASTER_TEL; + $_MASTER_FAX = _MASTER_FAX; + $_MASTER_ADDR = _MASTER_ADDR; + } + + $_lang_check = ($language != "ko") ? "_".$language : ""; + + include_once $_SERVER['DOCUMENT_ROOT'].'/language/'.$language_file; +?> diff --git a/common/conf/config.php b/common/conf/config.php new file mode 100644 index 0000000..f1e9785 --- /dev/null +++ b/common/conf/config.php @@ -0,0 +1,215 @@ + $value1) { + $out[(string)$value1] = $arr2[$key1]; + } + + return $out; + } + } + + $_CODE = array( + "1" => array( // 회원 등급 + "1" => "관리자", + //"3" => "직원", + //"5" => "정회원", + //"7" => "준회원", + "10" => "탈퇴/비회원" + ), + "2" => array( + "Y" => "예", + "N" => "아니요" + ), + "3" => array( + "0" => "출력안함", + "1" => "셀렉트박스", + "2" => "이미지", + "3" => "텍스트" + ), + //이메일 + "5" => array( + "1" => "naver.com", + "2" => "nate.com", + "3" => "hanmail.net", + "4" => "gmail.com", + "5" => "paran.com", + "6" => "freechal.com", + "7" => "hotmail.com", + "8" => "lycos.com", + "9" => "netsgo.com", + "10" => "empas.com", + "11" => "empal.com", + "12" => "yahoo.co.kr", + "13" => "dreamwiz.co.kr", + "15" => "Direct input" + ), + + //연락처 + "6" => array( + "1" => array( + "1" => "010", + "2" => "011", + "3" => "016", + "4" => "017", + "5" => "018", + "6" => "019" + ), + "2" => array( + "1" => "010", + "2" => "011", + "3" => "016", + "4" => "017", + "5" => "018", + "6" => "019", + "7" => "070", + "8" => "02", + "9" => "031", + "10" => "032", + "11" => "033", + "12" => "041", + "13" => "042", + "14" => "043", + "15" => "051", + "16" => "052", + "17" => "053", + "18" => "054", + "19" => "055", + "20" => "061", + "21" => "062", + "22" => "063", + "23" => "064" + ) + ), + + + "9" => array( + "N" => "미확인", + "I" => "처리완료", + ), + + ); + + //게시판 코드 + $_BOARD_CONFIG_CODE = array( + + "1" => array( // 게시판 권한 + "1" => "관리자", + //"3" => "직원", + //"5" => "정회원", + //"7" => "준회원", + "10" => "탈퇴/비회원" + ), + "2" => array( + "Y" => "예", + "N" => "아니요" + ), + "3" => array( //카테고리 출력여부 + "0" => "출력안함", + "1" => "셀렉트박스", + "2" => "이미지", + "3" => "텍스트" + ), + "4" => array( //게시판 정렬 + "1" => "가운데", + "2" => "왼쪽", + "3" => "오른쪽" + ) + + ); + + define('G5_STRING_ENCRYPT_FUNCTION', 'sql_password'); + + # URL 및 경로 설정 + $_ServerRoot = $_SERVER["DOCUMENT_ROOT"]; + $_BASE_PATH = $_SERVER["DOCUMENT_ROOT"]."/"; + $_PDS = $_BASE_PATH."pds/"; + $_BASIC_HOME_URL = $_SERVER["HTTP_HOST"]; + $max_w = 1140; + + define("_BASE_PATH", $_BASE_PATH); + define("_PDS", $_PDS); + + define("_UPLOAD_SIZE", 5); // 파일 업로드 제한 용량(MB) + define("_MAX_W", $max_w); // 이미지 가로 사이즈 + + # URL 설정 + define("_BASIC_HOME_URL", "http://".$_BASIC_HOME_URL); # homepage URL + define("_MAIL_IMG_URL", _BASIC_HOME_URL."/img/mail"); # 메일 이미지 URL + + # 게시물 목록수 + DEFINE("BOARD_LIST_NUM", 20); + + # 게시판 페이징 버튼 + + DEFINE("BOARD_FIRST_IMG","/img/board/ll.png"); // 처음으로 + DEFINE("BOARD_LAST_IMG", "/img/board/rr.png"); // 끝으로 + DEFINE("BOARD_PREV_IMG", "/img/board/l.png"); // 이전 + DEFINE("BOARD_NEXT_IMG", "/img/board/r.png"); // 다음 +?> diff --git a/common/contact.php b/common/contact.php new file mode 100644 index 0000000..0cf1b68 --- /dev/null +++ b/common/contact.php @@ -0,0 +1,204 @@ + $fileobj){ + $_FILE_VALUE = $_FILES[$fname]; + + $tmp_file="tmp_".$fname; + $del_file="del_".$fname; + + if($_FILE_VALUE !== null && $_FILE_VALUE[error] == 0 && $_FILE_VALUE[size] > 0 ){// 첨부파일이 있을경우 + + + if(preg_match('/\\.(php|htm|html|asp|jsp|js|com|bat|exe|dl|dll)$/i', strtolower($_FILE_VALUE["name"]))){ // 확장자 금지항목 체크 + go_url(_BASIC_HOME_URL,"금지된 확장자의 파일 업로드를 시도하셨습니다."); + exit; + } + + $_sf_type = array_pop(explode(".",$_FILE_VALUE["name"])); + $_sf_type = strtolower($_sf_type); + $now = date('YmdHi'); + $rand = rand(1000,9999); + $_filename = $now."_".$rand.".".$_sf_type; + + if($_FILE_VALUE[size]>20*1024*1024){// 용량이 클 경우(20M) + go_url(_BASIC_HOME_URL,"업로드 제한용량을 초과하였습니다."); + exit; + }else{ + if(file_exists($_SERVER["DOCUMENT_ROOT"]."/pds/contact".$_filename)){ // 파일이 존재할 경우 + @unlink($_SERVER["DOCUMENT_ROOT"]."/pds/contact".$_filename); + } + + if(move_uploaded_file($_FILE_VALUE["tmp_name"], $_SERVER["DOCUMENT_ROOT"]."/pds/contact/".$_filename)){ + $_uploaded[$fname] = $_filename; + }else{ + go_url("","파일 업로드에 실패했습니다."); + exit; + } + } + }else{ + $_uploaded[$fname] = $argu[$tmp_file]; + } + + if($argu[$del_file]==1){ + @unlink($_SERVER["DOCUMENT_ROOT"]."/pds/contact/".$argu[$tmp_file]); + $_uploaded[$fname] = ""; + } + } + } + + return $_uploaded; +} + +function attach_file($name, $file) { + $fp = fopen($file, "r"); + $tmpfile = array( + "name" => $name, + "data" => $file); + //"data" => fread($fp, filesize($file))); + fclose($fp); + return $tmpfile; +} + +if(_SITE_KEY != "" && _SECRET_KEY != ""){ + if(isset($_POST['g-recaptcha-response'])){ + $captcha=$_POST['g-recaptcha-response']; + } + else{ + $captcha = false; + } + if(!$captcha){ + go_url("/customer3.php",$lang["MSG1"]); + exit; + } + $secret = _SECRET_KEY; + $response=file_get_contents("https://www.google.com/recaptcha/api/siteverify?secret=".$secret."&response=".$captcha."&remoteip=".$_SERVER['REMOTE_ADDR']); + + + if($response.success==true){ + if(is_array($_POST)){ + + $upfile = file_upload($argu); + $argu['upfile'] = $upfile["upfile"]; + $argu['upfile_ori'] = $_FILES["upfile"]["name"]; + + + if($Obj_contact -> set_insert($argu)){ + + + if(_SMTP_MAIL_ID != ""){ + ///메일 발송 + $HOST = _SMTP_MAIL_HOST; + $SMTP_MAIL_ID = _SMTP_MAIL_ID; + $SMTP_MAIL_PW = _SMTP_MAIL_PW; + $FROM_EMAIL = _SMTP_MAIL_ID; + $FROM_NAME = _MASTER_NAME; + + $SUBJECT = "["._MASTER_NAME."] ".$argu['name']."님 문의 접수."; + + $CONTENT = "

이름 : ".$argu['name']."

"; + $CONTENT .= "

연락처 : ".$argu['phone']."

"; + $CONTENT .= "

E-mail : ".$argu["email"]."

"; + $CONTENT .= nl2br($argu["content"]); + + $MAILTO = _MASTER_EMAIL; + $MAILTONAME = _MASTER_NAME; + if($SMTP_MAIL_ID != "" && $MAILTO != ""){ + //$file[0] = attach_file($_FILES["upfile"]["name"],$_SERVER["DOCUMENT_ROOT"]."/pds/contact/".$upfile["upfile"]); + $file = ""; + + $mail = send_smtp($HOST, $SMTP_MAIL_ID, $SMTP_MAIL_PW, $FROM_EMAIL, $FROM_NAME, $SUBJECT, $CONTENT, $MAILTO, $MAILTONAME, $file); + } + + } + //if($argu["phone"] != ""){ +// $_SMS_SENDER = _SMS_SENDER; +// $_SMS_MESG = $argu["name"]."님 께서 문의 하셨습니다.\n TEL : ".$argu["phone"]; +// $_SMS_DIVISION = "sms"; +// $_SMS_RECEIVERS = str_replace("-","",_SMS_RECEIVERS); +// $_SMS_SUBJECT = "블레싱 디자인"; +// +// if(_SMS_ID != "" && _SMS_PW != ""){ +// $_sms = SendSms($_SMS_SENDER,$_SMS_RECEIVERS,$_SMS_SUBJECT,$_SMS_MESG, $_SMS_DIVISION); +// } + //} + + go_url("/customer3.php",$lang["MSG2"]); + exit; + } + else{ + go_url("/customer3.php",$lang["MSG3"]); + exit; + } + } + + } + else{ + go_url("/customer3.php",$lang["MSG1"]); + exit; + } +} +else{ + if(is_array($_POST)){ + + $upfile = file_upload($argu); + $argu['upfile'] = $upfile["upfile"]; + $argu['upfile_ori'] = $_FILES["upfile"]["name"]; + + if($Obj_contact -> set_insert($argu)){ + + + if(_SMTP_MAIL_ID != ""){ + ///메일 발송 + $HOST = _SMTP_MAIL_HOST; + $SMTP_MAIL_ID = _SMTP_MAIL_ID; + $SMTP_MAIL_PW = _SMTP_MAIL_PW; + $FROM_EMAIL = _SMTP_MAIL_ID; + $FROM_NAME = _MASTER_NAME; + + $SUBJECT = "["._MASTER_NAME."] ".$argu['name']."님 문의 접수."; + + $CONTENT = "

이름 : ".$argu['name']."

"; + $CONTENT .= "

연락처 : ".$argu['phone']."

"; + $CONTENT .= "

E-mail : ".$argu["email"]."

"; + $CONTENT .= nl2br($argu["content"]); + + $MAILTO = _MASTER_EMAIL; + $MAILTONAME = _MASTER_NAME; + if($SMTP_MAIL_ID != "" && $MAILTO != ""){ + //$file[0] = attach_file($_FILES["upfile"]["name"],$_SERVER["DOCUMENT_ROOT"]."/pds/contact/".$upfile["upfile"]); + $file = ""; + + $mail = send_smtp($HOST, $SMTP_MAIL_ID, $SMTP_MAIL_PW, $FROM_EMAIL, $FROM_NAME, $SUBJECT, $CONTENT, $MAILTO, $MAILTONAME, $file); + } + + } + //if($argu["phone"] != ""){ +// $_SMS_SENDER = _SMS_SENDER; +// $_SMS_MESG = $argu["name"]."님 께서 문의 하셨습니다.\n TEL : ".$argu["phone"]; +// $_SMS_DIVISION = "sms"; +// $_SMS_RECEIVERS = str_replace("-","",_SMS_RECEIVERS); +// $_SMS_SUBJECT = "블레싱 디자인"; +// +// if(_SMS_ID != "" && _SMS_PW != ""){ +// $_sms = SendSms($_SMS_SENDER,$_SMS_RECEIVERS,$_SMS_SUBJECT,$_SMS_MESG, $_SMS_DIVISION); +// } + //} + + go_url("/customer3.php",$lang["MSG2"]); + exit; + } + else{ + go_url("/customer3.php",$lang["MSG3"]); + exit; + } + } +} + + +?> \ No newline at end of file diff --git a/common/download.php b/common/download.php new file mode 100644 index 0000000..10edc98 --- /dev/null +++ b/common/download.php @@ -0,0 +1,36 @@ +alert('첨부파일이 존재하지 않습니다.');history.go(-1);"; + exit; + } + + $file = "../pds/".$_GET['fullpath']; + $filename = $_GET['filename']; + $filename = iconv('UTF-8', 'cp949//IGNORE', $filename); + + if( strstr($HTTP_USER_AGENT,"MSIE 5.5")){ + Header("Content-Type: doesn/matter"); + Header("content-length: ". filesize("$file")); + Header("Content-Disposition: attachment; filename=$filename"); + Header("Content-Transfer-Encoding: binary"); + Header("Cache-Control: cache,must-revalidate"); + Header("Pragma: cache"); + Header("Expires: 0"); + }else{ + Header("Content-type: file/unknown"); + Header("content-length: ". filesize("$file")); + Header("Content-Disposition: attachment; filename=$filename"); + Header("Content-Description: PHP3 Generated Data"); + Header("Cache-Control: cache,must-revalidate"); + Header("Pragma: cache"); + Header("Expires: 0"); + } + + if(is_file("$file")){ + $fp = fopen("$file","r"); + if(!fpassthru($fp)) { + fclose($fp); + } + } +exit; +?> \ No newline at end of file diff --git a/common/images/1.gif b/common/images/1.gif new file mode 100644 index 0000000..076c753 Binary files /dev/null and b/common/images/1.gif differ diff --git a/common/images/b_02.gif b/common/images/b_02.gif new file mode 100644 index 0000000..e42fd65 Binary files /dev/null and b/common/images/b_02.gif differ diff --git a/common/images/btn_close.gif b/common/images/btn_close.gif new file mode 100644 index 0000000..5febc36 Binary files /dev/null and b/common/images/btn_close.gif differ diff --git a/common/images/btn_x.gif b/common/images/btn_x.gif new file mode 100644 index 0000000..9819a38 Binary files /dev/null and b/common/images/btn_x.gif differ diff --git a/common/images/graph.gif b/common/images/graph.gif new file mode 100644 index 0000000..7c82350 Binary files /dev/null and b/common/images/graph.gif differ diff --git a/common/images/j_02.gif b/common/images/j_02.gif new file mode 100644 index 0000000..153cce7 Binary files /dev/null and b/common/images/j_02.gif differ diff --git a/common/images/loading.gif b/common/images/loading.gif new file mode 100644 index 0000000..f864d5f Binary files /dev/null and b/common/images/loading.gif differ diff --git a/common/images/t_04.gif b/common/images/t_04.gif new file mode 100644 index 0000000..7dd7200 Binary files /dev/null and b/common/images/t_04.gif differ diff --git a/common/lib/class.banner.php b/common/lib/class.banner.php new file mode 100644 index 0000000..711221e --- /dev/null +++ b/common/lib/class.banner.php @@ -0,0 +1,335 @@ +DB = $db; + $this->_PDS .= $this->_PDS_SUB; + } + + #등록# + function set_insert($argu){ + + $order_num = $this->DB->getOne("select coalesce(max(order_num),0)+1 from ".TABLE_BANNER." where (division = '".$argu["division"]."')"); + if (DB::isError($res)) { + go_url("","등록에 실패했습니다!\\n[".$res->getMessage()."]"); + exit; + } + + //파일 업로드 + /*if($argu["division"] == "T"){ + $_banner_thumb = thumb_upload($_FILES['image'],'/pds/banner/','O',$argu["division"]); + } + else if($argu["division"] == "R"){ + $_banner_thumb = thumb_upload($_FILES['image'],'/pds/banner/','O',$argu["division"]); + }*/ + $_banner_thumb = thumb_upload($_FILES['image'],'/pds/banner/','O',$argu["division"]); + + + $data = array( + "division" => $argu["division"], + "image" => $_banner_thumb, + "order_num" => $order_num, + "url" => $argu["url"], + "target" => $argu["target"], + "published" => $argu["published"], + "title" => $argu["title"], + "description" => $argu["description"], + "url_title" => $argu["url_title"], + "text_use" => $argu["text_use"], + "gubun" => $argu["gubun"] + ); + + $sth = $this->DB->autoPrepare(TABLE_BANNER, array_keys($data), DB_AUTOQUERY_INSERT); + $res = $this->DB->execute($sth, array_values($data)); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $b_id=mysql_insert_id(); + + $data=array_merge($data,array("b_id"=>$b_id)); + + return $data; + + } + + + #수정# + function set_modify($argu){ + + //파일 업로드 + /*if($argu["division"] == "T"){ + if($_FILES['image']['tmp_name']){ + $_banner_thumb = thumb_upload($_FILES['image'],'/pds/banner/','O',$argu["division"]); + unlink($_SERVER["DOCUMENT_ROOT"]."/pds/banner/".$argu["tmp_image"]); + } + else{ + $_banner_thumb = $argu["tmp_image"]; + } + } + else if($argu["division"] == "R"){ + if($_FILES['image']['tmp_name']){ + $_banner_thumb = thumb_upload($_FILES['image'],'/pds/banner/','O',$argu["division"]); + unlink($_SERVER["DOCUMENT_ROOT"]."/pds/banner/".$argu["tmp_image"]); + } + else{ + $_banner_thumb = $argu["tmp_image"]; + } + }*/ + if($_FILES['image']['tmp_name']){ + $_banner_thumb = thumb_upload($_FILES['image'],'/pds/banner/','O',$argu["division"]); + unlink($_SERVER["DOCUMENT_ROOT"]."/pds/banner/".$argu["tmp_image"]); + } + else{ + $_banner_thumb = $argu["tmp_image"]; + } + + $data = array( + "division" => $argu["division"], + "image" => $_banner_thumb, + "published" => $argu["published"], + "url" => $argu["url"], + "target" => $argu["target"], + "title" => $argu["title"], + "description" => $argu["description"], + "url_title" => $argu["url_title"], + "text_use" => $argu["text_use"], + "gubun" => $argu["gubun"] + ); + + $res = $result = $this->DB->autoExecute(TABLE_BANNER, $data, DB_AUTOQUERY_UPDATE, " b_id = '{$argu['b_id']}' "); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return true; + } + + + #삭제# + function set_delete($b_id){ + $_row = $this -> get_view($b_id); + + if($_row["image"]){ + unlink($_SERVER["DOCUMENT_ROOT"]."/pds/banner/".$_row["image"]); + } + + $query = "DELETE FROM ".TABLE_BANNER." WHERE b_id = '".$b_id."'"; + + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + + #리스트삭제# + function set_delete_list($argu){ + if(count($argu["chk"]) > 0){ + for($i = 0; $i < count($argu["chk"]); $i++){ + $b_id = $argu["chk"][$i]; + $_list = $this -> set_delete($b_id); + } + return true; + } + else{ + go_url("","삭제할데이터가 없습니다."); + exit; + } + } + + + #리스트# + function get_list($argu,&$total,$limit = true){ + global $_adminpage; + + $addwhere = " where (1=1) "; + if($argu["division"]){$addwhere .= " and (division = '".$argu["division"]."')";} + + /// 검색쿼리 + if($argu['s_string']){ $addwhere .= " and title like '%{$argu['s_string']}%' "; } + + if($argu['gubun']){ $addwhere .= " and gubun = '{$argu['gubun']}' "; } + + $query = " + select + count(*) + from + ".TABLE_BANNER." + ".$addwhere; + + $res = $total = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = " + select + * + from + ".TABLE_BANNER." + ".$addwhere." + order by + order_num asc + "; + if($limit) + $query .= " + limit ".($argu['p']-1)*$this->_LIST_NUM.",".$this->_LIST_NUM; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + + } + + + #상세보기 + function get_view($b_id){ + $query = "SELECT + * + FROM ".TABLE_BANNER." + where b_id = '".$b_id."'"; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $row; + + } + + + #메인비주얼리스트# + function get_main($division,$lang){ + $addwhere = "WHERE (published = 'Y') and (division = '".$division."') and (gubun = '".$lang."')"; + + $query = "SELECT + * + FROM ".TABLE_BANNER." + ".$addwhere." + ORDER BY order_num asc"; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + + + + /***** + *정렬값을 수정한다. + *****/ + function set_order($argu){ + + if($argu["s_mode"] == "up"){ + + $res = $b_id = $this->DB->getOne("select b_id from ".TABLE_BANNER." where (order_num < '".$argu["order_num"]."') and (division = '".$argu["division"]."') order by order_num desc limit 1"); + + if($b_id){ + + $query = " + update ".TABLE_BANNER." + set + order_num = order_num - 1 + where + b_id = '".$argu["b_id"]."' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query1 = " + update ".TABLE_BANNER." + set + order_num = order_num + 1 + where + b_id = '".$b_id."' + "; + + $res1 = $this->DB->query($query1); + if (DB::isError($res1)) { + go_url("", $res1->getMessage()); + exit; + } + + } + else{ + go_url("", "정열값이 최상위 입니다."); + exit; + } + + } + else if($argu["s_mode"] == "down"){ + $res = $b_id = $this->DB->getOne("select b_id from ".TABLE_BANNER." where (order_num > '".$argu["order_num"]."') and (division = '".$argu["division"]."') order by order_num asc limit 1"); + + if($b_id){ + + $query = " + update ".TABLE_BANNER." + set + order_num = order_num + 1 + where + b_id = '".$argu["b_id"]."' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query1 = " + update ".TABLE_BANNER." + set + order_num = order_num - 1 + where + b_id = '".$b_id."' + "; + + $res1 = $this->DB->query($query1); + if (DB::isError($res1)) { + go_url("", $res1->getMessage()); + exit; + } + + } + else{ + go_url("", "정열값이 최하위 입니다."); + exit; + } + } + + return true; + } + + + + } +?> \ No newline at end of file diff --git a/common/lib/class.board.php b/common/lib/class.board.php new file mode 100644 index 0000000..84a27fd --- /dev/null +++ b/common/lib/class.board.php @@ -0,0 +1,2268 @@ +DB = $db; + $this->_PDS .= $this->_PDS_SUB; + } + + /****************************************************************************************** + + Board_config + + ******************************************************************************************/ + + /***** + * 게시판을 등록한다. + *****/ + function set_boardconf_insert($argu){ + $res = $b_class = $this->DB->getOne("select coalesce(max(b_class),0)+1 from ".TABLE_BOARD_CONFIG); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + if(!$argu["b_type"]) $argu["b_type"] = $this->_default_b_type; + + $data = array( + "b_class" => $b_class, + "bc_class" => $argu["bc_class"], + "bc_name" => $argu["bc_name"], + "b_role_w" => $argu["b_role_w"], + "b_role_r" => $argu["b_role_r"], + "b_role_l" => $argu["b_role_l"], + "b_role_rp" => $argu["b_role_rp"], + "b_role_cm" => $argu["b_role_cm"], + "b_role_category" => ($argu["b_role_category"]=="Y")?"Y":"N", + "b_role_hp" => ($argu["b_role_hp"]=="Y")?"Y":"N", + "b_role_em" => ($argu["b_role_em"]=="Y")?"Y":"N", + "b_role_mms" => ($argu["b_role_mms"]=="Y")?"Y":"N", + "b_role_md" => ($argu["b_role_md"]=="Y")?"Y":"N", + "b_role_cmt" => ($argu["b_role_cmt"]=="Y")?"Y":"N", + "b_role_secret" => ($argu["b_role_secret"]=="Y")?"Y":"N", + "b_role_fn" => ($argu["b_role_fn"]=="")? 0:$argu["b_role_fn"], + "b_category" => $argu["b_category"], + "b_category_print" => $argu["b_category_print"], + "b_listnum" => $argu["b_listnum"], + "b_type" => $argu["b_type"], + "b_header_file" => $argu["b_header_file"], + "b_header" => $argu["b_header"], + "b_footer_file" => $argu["b_footer_file"], + "b_footer" => $argu["b_footer"], + "b_size" => $argu["b_size"], + "b_align" => $argu["b_align"], + "b_status" => $argu["b_status"], + "user_id" => $argu["user_id"], + "b_role_thumb" => ($argu["b_role_thumb"]=="Y")?"Y":"N", + "b_role_thumb_w" => $argu["b_role_thumb_w"], + "b_role_thumb_vertical_w" => $argu["b_role_thumb_vertical_w"], + "b_role_thumb_list_w" => $argu["b_role_thumb_list_w"], + "b_role_notice" => ($argu["b_role_notice"]=="Y")?"Y":"N", + "b_role_editor" => ($argu["b_role_editor"]=="Y")?"Y":"N", + "b_role_content" => ($argu["b_role_content"]=="Y")?"Y":"N", + ); + + $sth = $this->DB->autoPrepare(TABLE_BOARD_CONFIG, array_keys($data), DB_AUTOQUERY_INSERT); + $res = $this->DB->execute($sth, array_values($data)); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + /***** + * 게시판을 수정한다. + *****/ + function set_boardconf_modify($argu){ + + if(!$argu["b_type"]) $argu["b_type"] = $this->_default_b_type; + + $data = array( + "bc_name" => $argu["bc_name"], + "bc_class" => $argu["bc_class"], + "b_role_w" => $argu["b_role_w"], + "b_role_r" => $argu["b_role_r"], + "b_role_l" => $argu["b_role_l"], + "b_role_rp" => $argu["b_role_rp"], + "b_role_cm" => $argu["b_role_cm"], + "b_role_category" => ($argu["b_role_category"]=="Y")?"Y":"N", + "b_role_hp" => ($argu["b_role_hp"]=="Y")?"Y":"N", + "b_role_em" => ($argu["b_role_em"]=="Y")?"Y":"N", + "b_role_mms" => ($argu["b_role_mms"]=="Y")?"Y":"N", + "b_role_md" => ($argu["b_role_md"]=="Y")?"Y":"N", + "b_role_cmt" => ($argu["b_role_cmt"]=="Y")?"Y":"N", + "b_role_secret" => ($argu["b_role_secret"]=="Y")?"Y":"N", + "b_role_fn" => ($argu["b_role_fn"]=="")? 0:$argu["b_role_fn"], + "b_category" => $argu["b_category"], + "b_category_print" => $argu["b_category_print"], + "b_listnum" => $argu["b_listnum"], + "b_type" => $argu["b_type"], + "b_header_file" => $argu["b_header_file"], + "b_header" => $argu["b_header"], + "b_footer_file" => $argu["b_footer_file"], + "b_footer" => $argu["b_footer"], + "b_size" => $argu["b_size"], + "b_align" => $argu["b_align"], + "b_status" => $argu["b_status"], + "user_id" => $argu["user_id"], + "b_role_thumb" => ($argu["b_role_thumb"]=="Y")?"Y":"N", + "b_role_thumb_w" => $argu["b_role_thumb_w"], + "b_role_thumb_vertical_w" => $argu["b_role_thumb_vertical_w"], + "b_role_thumb_list_w" => $argu["b_role_thumb_list_w"], + "b_role_notice" => ($argu["b_role_notice"]=="Y")?"Y":"N", + "b_role_editor" => ($argu["b_role_editor"]=="Y")?"Y":"N", + "b_role_content" => ($argu["b_role_content"]=="Y")?"Y":"N", + ); + + $res = $result = $this->DB->autoExecute(TABLE_BOARD_CONFIG, $data, + DB_AUTOQUERY_UPDATE, " b_class = '{$argu['b_class']}' "); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + /***** + * 게시판을 삭제한다. + *****/ + function set_boardconf_delete($argu){ + + $query = " + delete from ".TABLE_BOARD." + where b_class = '{$argu['b_class']}' + "; + $res = $this->DB->query($query); + + // 게시판을 삭제한다. + $query = " + delete from ".TABLE_BOARD_CONFIG." + where b_class = '{$argu['b_class']}' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return true; + } + + #게시판 설정 리스트 삭제 처리 + function set_boardconf_delete_list($argu){ + + if(count($argu["chk"]) > 0){ + for($i = 0; $i < count($argu["chk"]); $i++){ + $argu["b_class"] = $argu["chk"][$i]; + $_list = $this -> set_boardconf_delete($argu); + } + + return true; + } + else{ + go_url("","삭제할데이터가 없습니다."); + exit; + } + } + + + /***** + * 게시판 목록을 가져온다. + *****/ + function get_boardconf_list($argu,&$total,$limit = true){ + /// 분류 + $addwhere = ($argu['bconf_class']>0) ? " where bc.bc_class='".$argu['bconf_class']."'" : ""; + + $query = " + select + count(*) + from + ".TABLE_BOARD_CONFIG." bc + ".$addwhere; + + $res = $total = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = " + select + bc.b_class, + bc.bc_class, + bc.bc_name, + bc.b_role_w, + bc.b_role_r, + bc.b_role_category, + bc.b_role_hp, + bc.b_role_em, + bc.b_role_mms, + bc.b_role_md, + bc.b_role_secret, + bc.b_role_fn, + bc.b_category, + bc.b_category_print, + bc.b_listnum, + bc.b_type, + bc.b_status, + bc.user_id + from + ".TABLE_BOARD_CONFIG." bc + ".$addwhere." + order by + bc.bc_class asc, + bc.b_class asc "; + if($limit) + $query .= " + limit ".($argu['p']-1)*$this->_LIST_NUM.",".$this->_LIST_NUM; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + /***** + * 게시판 설정을 가져온다. + *****/ + function get_boardconf_view($b_class){ + $query = " + select + bc.b_class, + bc.bc_class, + bc.bc_name, + bc.b_role_w, + bc.b_role_r, + bc.b_role_l, + bc.b_role_rp, + bc.b_role_cm, + bc.b_role_category, + bc.b_role_hp, + bc.b_role_em, + bc.b_role_mms, + bc.b_role_md, + bc.b_role_secret, + bc.b_role_cmt, + ifnull(bc.b_role_fn,0) as b_role_fn, + bc.b_category, + bc.b_category_print, + bc.b_listnum, + bc.b_type, + bc.b_header_file, + bc.b_header, + bc.b_footer_file, + bc.b_footer, + bc.b_size, + bc.b_align, + bc.b_status, + bc.user_id, + bc.b_role_thumb, + bc.b_role_thumb_w, + bc.b_role_thumb_vertical_w, + bc.b_role_thumb_list_w, + bc.b_role_notice, + bc.b_role_editor, + b_role_content + from + ".TABLE_BOARD_CONFIG." bc + where + bc.b_class = '{$b_class}' + "; + + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + $this->_b_class = $row['b_class']; + $this->_bc_class = $row['bc_class']; + $this->_bc_name = $row['bc_name']; + $this->_b_role_w = $row['b_role_w']; + $this->_b_role_r = $row['b_role_r']; + $this->_b_role_l = $row['b_role_l']; + $this->_b_role_rp = $row['b_role_rp']; + $this->_b_role_cm = $row['b_role_cm']; + $this->_b_role_category = $row['b_role_category']; + $this->_b_role_hp = $row['b_role_hp']; + $this->_b_role_em = $row['b_role_em']; + $this->_b_role_mms = $row['b_role_mms']; + $this->_b_role_md = $row['b_role_md']; + $this->_b_role_fn = $row['b_role_fn']; + $this->_b_role_secret = $row['b_role_secret']; + $this->_b_role_cmt = $row['b_role_cmt']; + $this->_b_type = $row['b_type']; + $this->_b_header_file = $row['b_header_file']; + $this->_b_header = $row['b_header']; + $this->_b_footer_file = $row['b_footer_file']; + $this->_b_footer = $row['b_footer']; + $this->_b_size = $row['b_size']; + $this->_b_align = $row['b_align']; + $this->_b_category = $row['b_category']; + $this->_b_category_print = $row['b_category_print']; + $this->_b_bgcolor = $row['b_bgcolor']; + $this->_b_listnum = $row['b_listnum']; + $this->_b_status = $row['b_status']; + $this->_user_id = $row['user_id']; + $this->_PDS .= $this->_b_class."/"; + + $this->_b_role_thumb = $row['b_role_thumb']; + $this->_b_role_thumb_w = $row['b_role_thumb_w']; + $this->_b_role_thumb_vertical_w = $row['b_role_thumb_vertical_w']; + $this->_b_role_thumb_list_w = $row['b_role_thumb_list_w']; + $this->_b_role_notice = $row['b_role_notice']; + $this->_b_role_editor = $row['b_role_editor']; + $this->_b_role_content = $row['b_role_content']; + + return $row; + } + + /****************************************************************************************** + + Board + + ******************************************************************************************/ + + /***** + * 게시판을 등록한다. + *****/ + function set_board_insert($argu){ + + global $_ADMIM_PWD; + // 첨부파일 argu 를 정리한다. + if(is_array($_FILES['bf_file']['tmp_name'])){ + foreach($_FILES['bf_file'] as $_FILE_KEY => $tmp){ + foreach($tmp as $_FILE_NO => $_FILE_VALUE){ + $_FILE[$_FILE_NO][$_FILE_KEY] = $_FILE_VALUE; + } + } + } + + //$data['b_no'] = $this->DB->getOne("select ifnull(max(b_no),0)+1 from ".TABLE_BOARD." where b_class = '{$argu['b_class']}'"); + $res = $data['b_no'] = $this->DB->getOne("select ifnull(max(b_no),0)+1 from ".TABLE_BOARD." "); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + if($argu['b_no'] != ""){//답글일경우 + $query = " + select + b_top, + b_step, + case b_step + when '00' then 0 + else length(b_step)/2 + end as b_depth + from + ".TABLE_BOARD." + where + b_class = '{$argu['b_class']}' + and b_no = '{$argu['b_no']}' + "; + $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + + if($row['b_depth'] >= 49){ + go_url("","더이상 하위 답글을 쓰실수 없습니다!"); + exit; + } + + $query = " + select + max( + case + when length(substring(b.b_step,1,({$row['b_depth']}+1)*2)) < ({$row['b_depth']}+1)*2 then concat(substring(b.b_step,1,({$row['b_depth']}+1)*2), '00') + else substring(b.b_step,1,({$row['b_depth']}+1)*2) + end + ) + 1 + from + ".TABLE_BOARD." b + where + b.b_class = '{$argu['b_class']}' + and b.b_top = '{$row['b_top']}' + and + case + when {$row['b_depth']} > 0 then substring(b.b_step,1,({$row['b_depth']})*2) = substring('{$row['b_step']}',1,({$row['b_depth']})*2) + else 1 = 1 + end + "; + $data['b_step'] = $this->DB->getOne($query); + if(strlen($data['b_step'])%2 == 1) $data['b_step'] = '0'.$data['b_step']; + + $data['b_top'] = $row['b_top']; + + if(substr($data['b_step'], -2) == "00"){// 답글의 제한은 99개 까지이다. + go_url("","더이상 답글을 쓰실수 없습니다!"); + exit; + } + + /*********************** + 문의상담 답글시 메일 발송 + ************************/ + /*if($argu['b_class'] == "6"){ + + $mquery = " + select + b_name, + b_email + from + ".TABLE_BOARD." + where + b_class = '{$argu['b_class']}' + and b_no = '{$argu['b_no']}' + "; + $mrow = $this->DB->getRow($mquery,DB_FETCHMODE_ASSOC); + + if($mrow["b_email"] != ""){ + + $query = " + select + * + from + basic + "; + $_row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($_row)) { + //debug($row); + die($_row->getMessage()); + } + + $subject = "케이에스 차량 탁송에서 ".$mrow["b_name"]. "님이 문의하신 내용의 답변이 도착했습니다."; + include "../www/mail.html"; + // type : text=0, html=1, text+html=2 + mailer($_row["b_title"], $_row["b_email"], $mrow["b_email"], $subject, $mail_content, 1, $file="", $cc="", $bcc=""); + } + }*/ + + }else{//답글이 아닐경우 + $data['b_top'] = $data['b_no']; + $data['b_step'] = "00"; + } + + $data['b_pwd'] = ($argu['b_pwd'] == "" && $_SESSION['user_level'] > 1)? get_encrypt_string($_ADMIM_PWD):get_encrypt_string($argu['b_pwd']); + + if(isset($argu["b_mms"])) $data["b_mms"] = $argu["b_mms"]; + if(isset($argu["b_link"])) $data["b_link"] = $argu["b_link"]; + if(isset($argu["b_summary"])) $data["b_summary"] = $argu["b_summary"]; + if(isset($argu["b_status"])) $data["b_status"] = $argu["b_status"]; + + if(isset($argu["a_id"])) $data["a_id"] = $argu["a_id"]; + + + if($_FILES['b_thumb'] !== null && $_FILES['b_thumb'][error] == 0 && $_FILES['b_thumb'][size] > 0 ){ + $b_thumb_info = getimagesize($_FILES["b_thumb"]["tmp_name"]); + $b_thumb_width = $b_thumb_info[0]; //이미지 가로 사이즈 + $b_thumb_height = $b_thumb_info[1]; //이미지 세로 사이즈 + $b_thumb_type = $_FILES['b_thumb']['type']; + + if($b_thumb_width > $b_thumb_height){ + if($b_thumb_width > $this->_b_role_thumb_w){ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','T',$this->_b_role_thumb_w); + } + else{ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','O',''); + } + } + else if($b_thumb_width < $b_thumb_height){ + if($b_thumb_width > $this->_b_role_thumb_vertical_w){ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','T',$this->_b_role_thumb_vertical_w); + } + else{ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','O',''); + } + } + else{ + if($b_thumb_width > $this->_b_role_thumb_w){ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','T',$this->_b_role_thumb_w); + } + else{ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','O',''); + } + } + + if($b_thumb_width > $this->_b_role_thumb_list_w){ + $b_thumb_list = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb_list/','T',$this->_b_role_thumb_list_w); + } + else{ + $b_thumb_list = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb_list/','O',''); + } + } + + $data = array_merge($data,array( + "b_class" => $argu["b_class"], + "b_category" => $argu["b_category"], + "b_name" => $argu["b_name"], + "user_id" => $_SESSION['user_id'], + "b_title" => $argu["b_title"], + "b_notice" => ($argu["b_notice"]==1)?1:9, + "b_tag" => $argu["b_tag"], + "b_homepage" => $argu["b_homepage"], + "b_email" => $argu["b_email"], + "b_content" => ($argu["b_tag"] == "Y")? txtParse($argu["b_content"],1):strip_tags($argu["b_content"]), + "b_regdate" => date("Y-m-d H:i:s"), + "b_ip" => $_SERVER['REMOTE_ADDR'], + "b_secert" => ($argu["b_secert"]=="Y")?"Y":"N", + "b_front" => ($argu["b_front"]=="Y")?"Y":"N", + "b_tel" => $argu["b_tel"], + "b_etc1" => $argu["b_etc1"], + "b_etc2" => $argu["b_etc2"], + "b_etc3" => $argu["b_etc3"], + "b_etc4" => $argu["b_etc4"], + "b_etc5" => $argu["b_etc5"], + "b_etc6" => $argu["b_etc6"], + "b_etc7" => $argu["b_etc7"], + "b_etc8" => $argu["b_etc8"], + "b_etc9" => $argu["b_etc9"], + "b_etc10" => $argu["b_etc10"], + "b_thumb" => $b_thumb, + "b_thumb_list" => $b_thumb_list + )); + + $res = $this->DB->autoExecute(TABLE_BOARD, $data, DB_AUTOQUERY_INSERT); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + + // 첨부파일 저장 + // TODO : board_config 의 media 여부에 따라 허용 파일 타입을 필터링 해주는 부분이 필요하다. + if(is_array($_FILE)){ + foreach($_FILE as $_FILE_NO => $_FILE_VALUE){ + //$data['bf_name'] = upload_($this->_PDS, $_FILE_VALUE, $data['b_no']."_".$_FILE_NO, "U", &$M); + if($_FILE_VALUE !== null && $_FILE_VALUE[error] == 0 && $_FILE_VALUE[size] > 0 ){// 첨부파일이 있을경우 + + $_ext = array_pop(explode(".",$_FILE_VALUE[name])); + + /*if($argu["b_class"] == "1" || $argu["b_class"] == "2" || $argu["b_class"] == "3" || $argu["b_class"] == "4" || $argu["b_class"] == "5" || $argu["b_class"] == "6" || $argu["b_class"] == "7" ){*/ + $_file_name = $data['b_no']."_".$_FILE_NO.".".$_ext; + /*} + else{ + $_file_name = $data['b_no']."_".$_FILE_NO; + }*/ + + if(upload($this->_PDS, $_FILE_VALUE,$_file_name,"U")){ // 첨부파일 업로드에 성공했을경우 + $data["bf_name"] = $_FILE_VALUE[name]; + $data["bf_type"] = array_pop(explode(".",$data["bf_name"])); + }else{ // 첨부파일 업로드에 실패했을경우 alert 과 동시에 작업을 중단하고 이전페이지로 돌아간다. + go_url("","파일 업로드에 실패했습니다."); + exit; + } + + $data_file = array( + "b_class" => $data['b_class'], + "b_no" => $data['b_no'], + "bf_no" => $_FILE_NO, + "bf_type" => strtolower($data["bf_type"]), + "bf_name" => $data["bf_name"] + ); + + $res = $this->DB->autoExecute(TABLE_BOARD_FILE, $data_file, DB_AUTOQUERY_INSERT); + if (DB::isError($res)) { + go_url("","파일 업로드에 실패했습니다."); + exit; + } + } + } + } + + // 비밀글이라면 세션에 비밀글의 아이디를 저장한다. 자신의 글은 다시 패스워드를 묻지 않기 위함 + if ($argu["b_secert"]=="Y") + set_session("ss_secret_{$argu['b_class']}_{$data['b_no']}", TRUE); + + return true; + } + + /***** + * 게시판을 수정한다. + *****/ + function set_board_modify($argu){ + global $_ADMIM_PWD,$_adminpage; + // 첨부파일 argu 를 정리한다. + if(is_array($_FILES['bf_file']['tmp_name'])){ + foreach($_FILES['bf_file'] as $_FILE_KEY => $tmp){ + foreach($tmp as $_FILE_NO => $_FILE_VALUE){ + $_FILE[$_FILE_NO][$_FILE_KEY] = $_FILE_VALUE; + } + } + } + + if(!$_adminpage){ + $data['b_pwd'] = ($argu['b_pwd'] == "" && $_SESSION['user_level'] > 1)? get_encrypt_string($_ADMIM_PWD):get_encrypt_string($argu['b_pwd']); + } + + if(isset($argu["b_front"])) $data['b_front'] = $argu["b_front"]; + if(isset($argu["b_category"])) $data["b_category"] = $argu["b_category"]; + if(isset($argu["b_name"])) $data["b_name"] = $argu["b_name"]; + if(isset($argu["b_mms"])) $data["b_mms"] = $argu["b_mms"]; + if(isset($argu["b_link"])) $data["b_link"] = $argu["b_link"]; + if(isset($argu["b_summary"])) $data["b_summary"] = $argu["b_summary"]; + if(isset($argu["b_status"])) $data["b_status"] = $argu["b_status"]; + + + if($_FILES['b_thumb'] !== null && $_FILES['b_thumb'][error] == 0 && $_FILES['b_thumb'][size] > 0 ){ + $b_thumb_info = getimagesize($_FILES["b_thumb"]["tmp_name"]); + $b_thumb_width = $b_thumb_info[0]; //이미지 가로 사이즈 + $b_thumb_height = $b_thumb_info[1]; //이미지 세로 사이즈 + $b_thumb_type = $_FILES['b_thumb']['type']; + + if($b_thumb_width > $b_thumb_height){ + if($b_thumb_width > $this->_b_role_thumb_w){ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','T',$this->_b_role_thumb_w,$argu["tmp_b_thumb"]); + } + else{ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','O','',$argu["tmp_b_thumb"]); + } + } + else if($b_thumb_width < $b_thumb_height){ + if($b_thumb_width > $this->_b_role_thumb_vertical_w){ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','T',$this->_b_role_thumb_vertical_w,$argu["tmp_b_thumb"]); + } + else{ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','O','',$argu["tmp_b_thumb"]); + } + } + else{ + if($b_thumb_width > $this->_b_role_thumb_w){ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','T',$this->_b_role_thumb_w,$argu["tmp_b_thumb"]); + } + else{ + $b_thumb = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb/','O','',$argu["tmp_b_thumb"]); + } + } + + if($b_thumb_width > $this->_b_role_thumb_list_w){ + $b_thumb_list = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb_list/','T',$this->_b_role_thumb_list_w,$argu["tmp_b_thumb_list"]); + } + else{ + $b_thumb_list = board_thumb_upload($_FILES['b_thumb'],$this->_PDS.'thumb_list/','O','',$argu["tmp_b_thumb_list"]); + } + + } + else{ + $b_thumb = $argu["tmp_b_thumb"]; + $b_thumb_list = $argu["tmp_b_thumb_list"]; + } + + + $data = array_merge($data,array( + "b_title" => $argu["b_title"], + "b_notice" => ($argu["b_notice"]==1)? 1:9, + "b_secert" => ($argu["b_secert"]=="Y")?"Y":"N", + "b_tag" => $argu["b_tag"], + "b_homepage" => $argu["b_homepage"], + "b_email" => $argu["b_email"], + "b_content" => ($argu["b_tag"] == "Y")? txtParse($argu["b_content"],1):strip_tags($argu["b_content"]), + "b_tel" => $argu["b_tel"], + "b_etc1" => $argu["b_etc1"], + "b_etc2" => $argu["b_etc2"], + "b_etc3" => $argu["b_etc3"], + "b_etc4" => $argu["b_etc4"], + "b_etc5" => $argu["b_etc5"], + "b_etc6" => $argu["b_etc6"], + "b_etc7" => $argu["b_etc7"], + "b_etc8" => $argu["b_etc8"], + //"b_etc9" => $argu["b_etc9"], + //"b_etc10" => $argu["b_etc10"], + "b_thumb" => $b_thumb, + "b_thumb_list" => $b_thumb_list + )); + + + // 관리자에서 조회수 수정 가능하게 해달란 요청에의한 추가 2006-03-27 1:28오후 + //if($argu["b_cnt"] !== null) $data = array_merge($data,array("b_cnt" => $argu["b_cnt"])); + + $res = $this->DB->autoExecute(TABLE_BOARD, $data, DB_AUTOQUERY_UPDATE, " b_class = '{$argu['b_class']}' and b_no = '{$argu['b_no']}'"); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + + // 첨부파일 저장 + // TODO : board_config 의 media 여부에 따라 허용 파일 타입을 필터링 해주는 부분이 필요하다. + if(is_array($_FILE)){ + foreach($_FILE as $_FILE_NO => $_FILE_VALUE){ + if($_FILE_VALUE !== null && $_FILE_VALUE[error] == 0 && $_FILE_VALUE[size] > 0 ){// 첨부파일이 있을경우 + + $_ext = array_pop(explode(".",$_FILE_VALUE[name])); + + /*if($argu["b_class"] == "1" || $argu["b_class"] == "2" || $argu["b_class"] == "3" || $argu["b_class"] == "4" || $argu["b_class"] == "5" || $argu["b_class"] == "6" || $argu["b_class"] == "7" ){*/ + $_file_name = $argu['b_no']."_".$_FILE_NO.".".$_ext; + /*} + else{ + $_file_name = $argu['b_no']."_".$_FILE_NO; + }*/ + + $this->set_boardfile_delete(array("b_class"=>$argu['b_class'],"b_no"=>$argu['b_no'],"bf_no"=>$_FILE_NO,"bf_type"=>$_ext)); + + if(upload($this->_PDS, $_FILE_VALUE,$_file_name,"U")){ // 첨부파일 업로드에 성공했을경우 + $data["bf_name"] = $_FILE_VALUE[name]; + $data["bf_type"] = array_pop(explode(".",$data["bf_name"])); + }else{ // 첨부파일 업로드에 실패했을경우 alert 과 동시에 작업을 중단하고 이전페이지로 돌아간다. + go_url("","파일 업로드에 실패했습니다."); + exit; + } + + $data_file = array( + "b_class" => $argu['b_class'], + "b_no" => $argu['b_no'], + "bf_no" => $_FILE_NO, + "bf_type" => strtolower($data["bf_type"]), + "bf_name" => $data["bf_name"] + ); + $res = $this->DB->autoExecute(TABLE_BOARD_FILE, $data_file, DB_AUTOQUERY_INSERT); + if (DB::isError($res)) { + go_url("","파일 업로드에 실패했습니다."); + exit; + } + } + } + } + + for($i=0;$iset_boardfile_delete(array( "b_class" => $argu['b_class'] , "b_no" => $argu['b_no'] , "bf_no" => $argu['del_file'][$i], "bf_type"=>"" )); + } + return true; + } + + function set_re_modify($argu){ + global $_ADMIM_PWD; + + $data = array( + "b_etc1" => (strip_tags($argu["b_etc10"]) != "") ? "Y" : "N", + "b_etc9" => date("Y-m-d H:i:s"), + "b_etc10" => strip_tags($argu["b_etc10"]) + ); + + + // 관리자에서 조회수 수정 가능하게 해달란 요청에의한 추가 2006-03-27 1:28오후 + //if($argu["b_cnt"] !== null) $data = array_merge($data,array("b_cnt" => $argu["b_cnt"])); + + $res = $this->DB->autoExecute(TABLE_BOARD, $data, DB_AUTOQUERY_UPDATE, " b_class = '{$argu['b_class']}' and b_no = '{$argu['b_no']}'"); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return true; + } + + /***** + * 게시물을 삭제한다. + *****/ + function set_board_delete($argu){ + $file_list = $this->get_boardfile_list($argu['b_class'],$argu['b_no']); + if(is_array($file_list)){ + foreach($file_list as $key => $value){ + $this->set_boardfile_delete($value); + } + } + + $_b_row = $this -> get_board_view($argu['b_class'],$argu['b_no']); + if($_b_row["b_thumb"]){ + if(file_exists($this->_PDS."thumb/".$_b_row["b_thumb"])) unlink($this->_PDS."thumb/".$_b_row["b_thumb"]); + } + if($_b_row["b_thumb_list"]){ + if(file_exists($this->_PDS."thumb_list/".$_b_row["b_thumb_list"])) unlink($this->_PDS."thumb_list/".$_b_row["b_thumb_list"]); + } + + preg_match_all("/]*src=[\"']?([^>\"']+)[\"']?[^>]*>/i", txtParse($_b_row['b_content'],2), $imgSRC); + + if(sizeof($imgSRC[1])){ + for($i=0; $i < sizeof($imgSRC[1]); $i++){ + $edit_file = $_SERVER['DOCUMENT_ROOT'].$imgSRC[1][$i]; + if(file_exists($edit_file)) unlink($edit_file); + } + } + + $query = " + delete from ".TABLE_BOARD." + where + b_class = '{$argu['b_class']}' + and b_no = '{$argu['b_no']}' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return true; + } + + #게시판 리스트 삭제 처리 + function set_board_delete_list($argu){ + if(count($argu["chk"]) > 0){ + for($i = 0; $i < count($argu["chk"]); $i++){ + $argu["b_no"] = $argu["chk"][$i]; + $_list = $this -> set_board_delete($argu); + } + + return true; + } + else{ + go_url("","삭제할데이터가 없습니다."); + exit; + } + } + + + /***** + * 해당 게시판 첨부파일을 삭제 한다. + *****/ + function set_boardfile_delete($argu){ + + if($argu["b_class"] == "1" || $argu["b_class"] == "2" || $argu["b_class"] == "3" || $argu["b_class"] == "4" || $argu["b_class"] == "5" || $argu["b_class"] == "6" || $argu["b_class"] == "7" ){ + if($argu["bf_type"] == ""){ + $query = " + select + bf_type + from + ".TABLE_BOARD_FILE." + where + b_class = '{$argu['b_class']}' + and b_no = '{$argu['b_no']}' + and bf_no = '{$argu['bf_no']}' + "; + + $res = $_ext = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + } + else{ + $_ext = $argu["bf_type"]; + } + $_file_name = $argu['b_no']."_".$argu['bf_no'].".".$_ext; + } + else{ + $_file_name = $argu['b_no']."_".$argu['bf_no']; + } + + + if(upload($this->_PDS, "",$_file_name,"D")){ // 첨부파일 업로드에 성공했을경우 + $query = " + delete from ".TABLE_BOARD_FILE." + where + b_class = '{$argu['b_class']}' + and b_no = '{$argu['b_no']}' + and bf_no = '{$argu['bf_no']}' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return true; + }else{ + return false; + } + } + + /***** + * 해당 게시판 목록을 가져온다. + *****/ + function get_board_list($argu,&$total,$limit = true){ + global $_adminpage,$_agency; + + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($argu['b_category']) $addwhere .= " and b.b_category = '{$argu['b_category']}' "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + if($argu['s_case'] && $argu['s_string']) $addwhere .= " and b.{$argu['s_case']} like '%{$argu['s_string']}%' "; + + if($argu['Search']) $addwhere .= " and (b.b_title like '%{$argu['Search']}%' or b.b_content like '%{$argu['Search']}%') "; + + if($argu['sdate'] && $argu['edate']){ + $addwhere .= " and ({$argu['sdate']} between b.b_etc1 and b.b_etc2 or {$argu['edate']} between b.b_etc1 and b.b_etc2) "; + } + + $query = " + select + count(*) + from + ".TABLE_BOARD." b + where + b.b_class = '{$argu['b_class']}' + and + case + when length(trim('$argu[s_case]')) = 0 then true + else + case '$argu[s_case]' + when 'b_title' then b.b_title + when 'b_content' then b.b_content + when 'b_name' then b.b_name + end + like ? + end + $addwhere + "; + + $res = $total = $this->DB->getOne($query,array("%{$argu[s_string]}%")); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + +// if($argu["b_class"] == "3" || $argu["b_class"] == "4"){ +// $_sort = "b.b_etc9 desc"; +// } +// else{ + $_sort = "b.b_notice asc, b.b_top desc, b.b_step asc"; +// } + + $query = " + select + b.b_class, + b.b_no, + b.b_top, + b.b_step, + case b.b_step + when '00' then 0 + else length(b.b_step)/2 + end as b_depth, + b.b_category, + b.b_name, + b.b_pwd, + b.b_secert, + b.user_id, + if(date_add(b.b_regdate, interval 3 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + date_format(b.b_regdate,'%b-%d-%Y') as b_date1, + b.b_regdate, + b.b_title, + b.b_notice, + b.b_tag, + b.b_homepage, + b.b_mms, + b.b_link, + b.b_summary, + b.b_email, + b.b_content, + b.b_ip, + b.b_cnt, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10, + b.b_thumb, + b.b_thumb_list, + b.a_id, + bf.bf_name, + (select ifnull(count(b_no),0) from board_comment where b_no=b.b_no) as cmt_cnt + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_BOARD_FILE." bf + on b.b_class = bf.b_class and b.b_no = bf.b_no and bf.bf_no = 0 + where + b.b_class = '{$argu['b_class']}' + and b.b_class= bc.b_class + and + case + when length(trim('$argu[s_case]')) = 0 then 1 + else + case '$argu[s_case]' + when 'b_title' then b.b_title + when 'b_content' then b.b_content + when 'b_name' then b.b_name + end + like ? + end + $addwhere + group by + b.b_class, + b.b_no + order by + ".$_sort." "; + + if($argu["mobile_list_num"]){ + $this->_b_listnum = $argu["mobile_list_num"]; + } + + if($limit) + $query .= " + limit ".($argu['p']-1)*$this->_b_listnum.",".$this->_b_listnum; + + + $res = $list =& $this->DB->getAll($query, array("%{$argu[s_string]}%"), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $list; + } + + + function get_board_list_m($argu,&$total,$limit = true){ + global $_adminpage,$_agency; + + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($argu['b_category']) $addwhere .= " and b.b_category = '{$argu['b_category']}' "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + if($argu['s_case'] && $argu['s_string']) $addwhere .= " and b.{$argu['s_case']} like '%{$argu['s_string']}%' "; + + $query = " + select + count(*) + from + ".TABLE_BOARD." b + where + b.b_class = '{$argu['b_class']}' + and + case + when length(trim('$argu[s_case]')) = 0 then true + else + case '$argu[s_case]' + when 'b_title' then b.b_title + when 'b_content' then b.b_content + when 'b_name' then b.b_name + end + like ? + end + $addwhere + "; + + $res = $total = $this->DB->getOne($query,array("%{$argu[s_string]}%")); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = " + select + b.b_class, + b.b_no, + b.b_top, + b.b_step, + case b.b_step + when '00' then 0 + else length(b.b_step)/2 + end as b_depth, + b.b_category, + b.b_name, + b.b_pwd, + b.b_secert, + b.user_id, + if(date_add(b.b_regdate, interval 3 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + b.b_regdate, + b.b_title, + b.b_notice, + b.b_tag, + b.b_homepage, + b.b_mms, + b.b_link, + b.b_summary, + b.b_email, + b.b_content, + b.b_ip, + b.b_cnt, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10, + b.a_id, + bf.bf_name + -- ifnull(count(bf.bf_no),0) as bf_cnt + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_BOARD_FILE." bf + on b.b_class = bf.b_class and b.b_no = bf.b_no and bf.bf_no = 0 + where + b.b_class = '{$argu['b_class']}' + and b.b_class= bc.b_class + and + case + when length(trim('$argu[s_case]')) = 0 then 1 + else + case '$argu[s_case]' + when 'b_title' then b.b_title + when 'b_content' then b.b_content + when 'b_name' then b.b_name + end + like ? + end + $addwhere + group by + b.b_class, + b.b_no + order by + b.b_notice asc, b.b_top desc, b.b_step asc "; + if($limit) + $query .= " + limit ".(($argu['p']-1)*3).",3"; + + + $res = $list =& $this->DB->getAll($query, array("%{$argu[s_string]}%"), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $list; + } + + + /***** + * 관련글을 가져온다. + *****/ + function get_with_list($b_class,$b_top){ + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + + $query = " + select + b.b_class, + b.b_no, + b.b_top, + b.b_step, + case b.b_step + when '00' then 0 + else length(b.b_step)/2 + end as b_depth, + b.b_category, + b.b_name, + u.user_name, + b.b_pwd, + b.b_secert, + b.user_id, + if(date_add(b.b_regdate, interval 3 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + b.b_title, + b.b_tag, + b.b_homepage, + b.b_email, + b.b_mms, + b.b_link, + b.b_summary, + b.b_content, + b.b_ip, + b.b_cnt, + b.a_id, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10 + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_USER." u + on b.user_id = u.user_id + where + b.b_class = '{$b_class}' + and b.b_top = '{$b_top}' + and b.b_class= bc.b_class + $addwhere + order by + b.b_top desc, b_step asc + "; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $list; + } + + /***** + * 상위 일부 게시물을 가져온다. + *****/ + function get_board_limit($b_class,$limit=0,$b_category=''){ + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($b_category) $addwhere .= " and b.b_category = '{$b_category}' "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + + if($b_class == "3" || $b_class == "4"){ + $_sort = "b.b_etc9 desc"; + } + else{ + $_sort = "b.b_notice asc, b.b_top desc, b.b_step asc"; + } + + $query = " + select + b.b_class, + b.b_no, + b.b_notice, + b.b_top, + b.b_step, + case b.b_step + when '00' then 0 + else length(b.b_step)/2 + end as b_depth, + b.b_category, + b.b_name, + u.user_name, + b.b_pwd, + b.b_secert, + b.user_id, + if(date_add(b.b_regdate, interval 3 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + concat('[',date_format(b.b_regdate,'%y-%m-%d'),']') as b_date2, + date_format(b.b_regdate,'%Y') as b_date_main_y, + date_format(b.b_regdate,'%b') as b_date_main_m, + date_format(b.b_regdate,'%d') as b_date_main_d, + b.b_title, + b.b_tag, + b.b_homepage, + b.b_email, + b.b_mms, + b.b_link, + b.b_summary, + b.b_content, + b.b_ip, + b.b_cnt, + b.a_id, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10, + b.b_thumb, + b.b_thumb_list + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_USER." u + on b.user_id = u.user_id + where + b.b_class = '{$b_class}' + and b.b_class= bc.b_class + $addwhere + order by + ".$_sort." + limit ".$limit; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $list; + } + + + function get_board_asc($b_class){ + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($b_category) $addwhere .= " and b.b_category = '{$b_category}' "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + + $query = " + select + b.b_class, + b.b_no, + b.b_notice, + b.b_top, + b.b_step, + case b.b_step + when '00' then 0 + else length(b.b_step)/2 + end as b_depth, + b.b_category, + b.b_name, + u.user_name, + b.b_pwd, + b.b_secert, + b.user_id, + if(date_add(b.b_regdate, interval 3 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + concat('[',date_format(b.b_regdate,'%y-%m-%d'),']') as b_date2, + date_format(b.b_regdate,'%Y') as b_date_main_y, + date_format(b.b_regdate,'%M') as b_date_main_m, + date_format(b.b_regdate,'%d') as b_date_main_d, + b.b_title, + b.b_tag, + b.b_homepage, + b.b_email, + b.b_mms, + b.b_link, + b.b_summary, + b.b_content, + b.b_ip, + b.b_cnt, + b.a_id, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10 + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_USER." u + on b.user_id = u.user_id + where + b.b_class = '{$b_class}' + and b.b_class= bc.b_class + $addwhere + order by + b.b_top asc"; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $list; + } + + + function get_board_limit_notin($b_class,$b_no,$limit=0,$b_category=''){ + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($b_category) $addwhere .= " and b.b_category = '{$b_category}' "; + + $query = " + select + b.b_class, + b.b_no, + b.b_notice, + b.b_top, + b.b_step, + case b.b_step + when '00' then 0 + else length(b.b_step)/2 + end as b_depth, + b.b_category, + b.b_name, + u.user_name, + b.b_pwd, + b.b_secert, + b.user_id, + if(date_add(b.b_regdate, interval 3 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + concat('[',date_format(b.b_regdate,'%y-%m-%d'),']') as b_date2, + date_format(b.b_regdate,'%Y') as b_date_main_y, + date_format(b.b_regdate,'%M') as b_date_main_m, + date_format(b.b_regdate,'%d') as b_date_main_d, + b.b_title, + b.b_tag, + b.b_homepage, + b.b_email, + b.b_mms, + b.b_link, + b.b_summary, + b.b_content, + b.b_ip, + b.b_cnt, + b.a_id, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10 + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_USER." u + on b.user_id = u.user_id + where + b.b_class = '{$b_class}' + and b.b_no not in({$b_no}) + and b.b_class= bc.b_class + $addwhere + order by + b.b_notice asc,b.b_top desc, b_step asc + limit ".$limit; + + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $list; + } + + + function get_board_notin($b_class,$b_no,$b_category=''){ + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($b_category) $addwhere .= " and b.b_category = '{$b_category}' "; + + $query = " + select + b.b_class, + b.b_no, + b.b_notice, + b.b_top, + b.b_step, + case b.b_step + when '00' then 0 + else length(b.b_step)/2 + end as b_depth, + b.b_category, + b.b_name, + u.user_name, + b.b_pwd, + b.b_secert, + b.user_id, + if(date_add(b.b_regdate, interval 3 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + concat('[',date_format(b.b_regdate,'%y-%m-%d'),']') as b_date2, + date_format(b.b_regdate,'%Y') as b_date_main_y, + date_format(b.b_regdate,'%M') as b_date_main_m, + date_format(b.b_regdate,'%d') as b_date_main_d, + b.b_title, + b.b_tag, + b.b_homepage, + b.b_email, + b.b_mms, + b.b_link, + b.b_summary, + b.b_content, + b.b_ip, + b.b_cnt, + b.a_id, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10 + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_USER." u + on b.user_id = u.user_id + where + b.b_class = '{$b_class}' + and b.b_no not in({$b_no}) + and b.b_class= bc.b_class + $addwhere + order by + b.b_notice asc,b.b_top desc, b_step asc"; + + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $list; + } + + + /***** + * event 게시물을 가져온다. + *****/ + function get_board_event($b_class,$b_category=''){ + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($b_category) $addwhere .= " and b.b_category in ('{$b_category}', 'All') "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + + $query = " + select + b.b_class, + b.b_no, + b.b_notice, + b.b_top, + b.b_step, + case b.b_step + when '00' then 0 + else length(b.b_step)/2 + end as b_depth, + b.b_category, + b.b_name, + u.user_name, + b.b_pwd, + b.b_secert, + b.user_id, + if(date_add(b.b_regdate, interval 3 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + concat('[',date_format(b.b_regdate,'%y-%m-%d'),']') as b_date2, + b.b_title, + b.b_tag, + b.b_homepage, + b.b_email, + b.b_mms, + b.b_link, + b.b_summary, + b.b_content, + b.b_ip, + b.b_cnt, + b.a_id, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10 + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_USER." u + on b.user_id = u.user_id + where + b.b_class = '{$b_class}' + and b.b_class= bc.b_class + /*and ('".date("Y-m-d")."' between b_etc1 and b_etc2)*/ + $addwhere + order by + b.b_notice asc,b.b_top desc, b_step asc"; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $list; + } + + + function set_board_cnt($b_class,$b_no){ + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + + // 한번 읽은글은 브라우저를 닫기전까지는 카운트를 증가시키지 않음 + $ss_name = "ss_view_{$b_class}_{$b_no}"; + if (!get_session($ss_name)) + { + // 조회수 증가 + $query = " + update ".TABLE_BOARD." b + set + b.b_cnt = b.b_cnt + 1 + where + b.b_class = '{$b_class}' + and b.b_no = '{$b_no}' + $addwhere + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + set_session($ss_name, TRUE); + } + } + + /***** + * 게시물 정보를 가져온다. + *****/ + function get_board_view($b_class,$b_no){ + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + + // 한번 읽은글은 브라우저를 닫기전까지는 카운트를 증가시키지 않음 + $ss_name = "ss_view_{$b_class}_{$b_no}"; + if (!get_session($ss_name)) + { + // 조회수 증가 + $query = " + update ".TABLE_BOARD." b + set + b.b_cnt = b.b_cnt + 1 + where + b.b_class = '{$b_class}' + and b.b_no = '{$b_no}' + $addwhere + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + set_session($ss_name, TRUE); + } + + $query = " + select + b.b_class, + b.b_no, + b.b_top, + b.b_step, + b.b_category, + b.b_name, + b.b_pwd, + b.b_secert, + b.user_id, + u.user_name, + if(date_add(b.b_regdate, interval 3 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + date_format(b.b_regdate,'%b-%d-%Y') as b_date1, + b.b_regdate, + b.b_title, + b.b_notice, + b.b_tag, + b.b_homepage, + b.b_email, + b.b_mms, + b.b_link, + b.b_summary, + b.b_content, + b.b_ip, + b.b_cnt, + b.a_id, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10, + b.b_thumb, + b.b_thumb_list + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_USER." u + on b.user_id = u.user_id + where + b.b_class = '{$b_class}' + and b.b_no = '{$b_no}' + and b.b_class= bc.b_class + $addwhere + "; + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $row; + } + + /***** + * 이전 게시물 정보를 가져온다. + *****/ + function get_board_prev($b_class,$b_no,$b_category){ + // TODO : 답변형의 경우 정확한 이전정보 가져오는 방법을 생각해보자 + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + if($b_category != "") $addwhere .= " and b.b_category = '{$b_category}' "; + + $query = " + select + b.b_class, + b.b_no, + b.b_category, + b.b_title, + b.a_id, + b.b_secert + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + where + b.b_class = '{$b_class}' + and b.b_no > '{$b_no}' + and b.b_class= bc.b_class + $addwhere + order by + b.b_top asc, b_step desc + limit 1 + "; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $row; + } + + /***** + * 다음 게시물 정보를 가져온다. + *****/ + function get_board_next($b_class,$b_no,$b_category){ + // TODO : 답변형의 경우 정확한 다음정보 가져오는 방법을 생각해보자 + global $_adminpage,$_agency; + $addwhere = ""; + if(!$_adminpage) $addwhere .= " and b.b_status = 'C' "; + if($argu['b_class']==3 && $_agency['a_id']) $addwhere .= " and b.a_id = '{$_agency['a_id']}' "; + if($b_category != "") $addwhere .= " and b.b_category = '{$b_category}' "; + + $query = " + select + b.b_class, + b.b_no, + b.b_category, + b.b_title, + b.a_id, + b.b_secert + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + where + b.b_class = '{$b_class}' + and b.b_no < '{$b_no}' + and b.b_class= bc.b_class + $addwhere + order by + b.b_top desc, b_step asc + limit 1 + "; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($row)) { + go_url("", $res->getMessage()); + exit; + } + return $row; + } + + /***** + * 게시물 첨부파일 정보를 가져온다. + *****/ + function get_boardfile_list($b_class,$b_no){ + $query = " + select + b_class, + b_no, + bf_no, + bf_type, + bf_name + from + ".TABLE_BOARD_FILE." bf + where + bf.b_class = '{$b_class}' + and bf.b_no = '{$b_no}' + "; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return $list; + } + + /****************************************************************************************** + + Board Vote + + ******************************************************************************************/ + + /***** + * 추천을 등록한다. + *****/ + function set_board_vote($b_class,$b_no,$user_id,$bv_score){ + if( $b_class && $b_no && $user_id &&$bv_score ){ + if(!$this->check_board_vote($b_class,$b_no,$user_id)){ + $data = array( + "b_class" => $b_class, + "b_no" => $b_no, + "user_id" => $user_id, + "bv_score" => $bv_score, + "bv_regdate" => date("Y-m-d H:i:s"), + "bv_ip" => $_SERVER['REMOTE_ADDR'], + ); + $res = $this->DB->autoExecute("board_vote", $data, DB_AUTOQUERY_INSERT); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + return true; + } + } + } + + /***** + * 추천정보를 가져온다. + *****/ + function get_board_vote($b_class,$b_no){ + $query = " + select + count(bv.user_id) as cnt, + sum(bv.bv_score) as sum, + format(avg(bv.bv_score),0) as avg + from + ".TABLE_BOARD_VOTE." bv + where + bv.b_class = ? + and bv.b_no = ? + "; + $res = $row = $this->DB->getRow($query,array($b_class,$b_no),DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $row; + } + + /***** + * 추천을 했는지 확인한다. + *****/ + function check_board_vote($b_class,$b_no,$user_id){ + if( $b_class && $b_no && $user_id ){ + $res = $check = $this->DB->getOne("select count(*) from board_vote where b_class = ? and b_no = ? and user_id = ? ",array($b_class,$b_no,$user_id)); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + if( $check > 0 ) return true; + else return false; + } + return false; + } + + /****************************************************************************************** + + Board Comment + + ******************************************************************************************/ + + /***** + * 댓글을 등록한다. + *****/ + function set_commemt_insert($argu){ + $data['bcm_no'] = $this->DB->getOne("select ifnull(max(bcm_no),0)+1 from board_comment + where bcm_gubun = '{$argu['bcm_gubun']}' and b_class = '{$argu['b_class']}' and b_no = '{$argu['b_no']}'"); + + if($argu["bcm_name"] == ""){ + $argu["bcm_name"] = $_SESSION['user_name']; + } + + $argu["bcm_pwd"] = substr(md5($argu["bcm_pwd"]),0,10); + + $data = array_merge($data,array( + "bcm_gubun" => $argu['bcm_gubun'], + "b_class" => $argu['b_class'], + "b_no" => $argu["b_no"], + "bcm_no" => $data['bcm_no'], + "bcm_name" => $argu["bcm_name"], + "bcm_pwd" => $argu["bcm_pwd"], + "bcm_comment" => $argu["bcm_comment"], + "bcm_date" => date("Y-m-d H:i:s"), + "user_id" => $_SESSION['user_id'], + "user_no" => $_SESSION['user_no'], + "bcm_ip" => $_SERVER['REMOTE_ADDR'], + )); + + $res = $this->DB->autoExecute("board_comment", $data, DB_AUTOQUERY_INSERT); + if (DB::isError($res)) { + go_url("","등록에 실패했습니다!\\n[".$res->getMessage()."]"); + exit; + } + return true; + } + + /***** + * 댓글내용을 가져온다. + *****/ + function get_comment_view($bcm_gubun,$b_class,$b_no,$bcm_no){ + $query = " + select + * + from + board_comment + where + bcm_gubun = '{$bcm_gubun}' + and b_class = '{$b_class}' + and b_no = '{$b_no}' + and bcm_no = '{$bcm_no}' + "; + + $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($row)) { + go_url("","댓글 내용을 가져오지 못했습니다."); + exit; + } + return $row; + } + + /***** + * 댓글목록을 가져온다. + *****/ + function get_comment_list($b_class,$b_no,$bcm_gubun = 'BD'){ + $query = " + select + bc.b_class, + bc.b_no, + bc.bcm_gubun, + bc.user_id, + bc.bcm_name, + u.user_name, + u.user_level, + bc.bcm_pwd, + bc.bcm_comment, + bc.bcm_date, + date_format(bc.bcm_date,'%Y.%m.%d') as bcm_date_name, + bc.bcm_ip, + bc.bcm_no + from + board_comment bc + left outer join ".TABLE_USER." u + on bc.user_id = u.user_id + where + bc.bcm_gubun = '{$bcm_gubun}' + and bc.b_class = '{$b_class}' + and bc.b_no = '{$b_no}' + order by bc.bcm_date desc + "; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("","댓글을 가져오지 못했습니다."); + exit; + } + return $list; + } + + /***** + * 댓글을 삭제 한다. + *****/ + function set_comment_delete($argu,$all = false){ + $query = " + delete from board_comment + where + bcm_gubun = '{$argu['bcm_gubun']}' + and b_class = '{$argu['b_class']}' + and b_no = '{$argu['b_no']}' "; + if(!$all) + $query .= " + and bcm_no = '{$argu['bcm_no']}' + "; + + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("","댓글이 삭제되지 않았습니다."); + exit; + } + return true; + } + + + /***** + * 게시판 권한 받기 + *****/ + function set_board_auth($mode){ + global $_SESSION; + $ses=$_SESSION; + + $isAuth=false; + + if($mode=="view"){ + if($ses['user_level']<=$this->_b_role_r && strlen($ses['user_id'])>3){ //사용자레벨이 게시판 권한설정값보다 작거나 같을시 + $isAuth=true; + } + else{ + if($this->_b_role_r >= 10){ //게시판 권한설정값이 비회원일시 + $isAuth=true; + } + else{ + $isAuth=false; + } + } + + } + + if($mode=="write"){ + if($ses['user_level']<=$this->_b_role_w && strlen($ses['user_id'])>3){ //사용자레벨이 게시판 권한설정값보다 작거나 같을시 + $isAuth=true; + } + else{ + if($this->_b_role_w >= 10){ //게시판 권한설정값이 비회원일시 + $isAuth=true; + } + else{ + $isAuth=false; + } + } + } + + if($mode=="replay"){ + + if($ses['user_level']<=$this->_b_role_rp && strlen($ses['user_id'])>3){ //사용자레벨이 게시판 권한설정값보다 작거나 같을시 + $isAuth=true; + } + else{ + if($this->_b_role_rp >= 10){ //게시판 권한설정값이 비회원일시 + $isAuth=true; + } + else{ + $isAuth=false; + } + } + } + + if($mode=="list"){ + + if($ses['user_level']<=$this->_b_role_l && strlen($ses['user_id'])>3){ //사용자레벨이 게시판 권한설정값보다 작거나 같을시 + $isAuth=true; + } + else{ + if($this->_b_role_l >= 10){ //게시판 권한설정값이 비회원일시 + $isAuth=true; + } + else{ + $isAuth=false; + } + } + } + + if($mode=="cm"){ + if($ses['user_level']<=$this->_b_role_cm && strlen($ses['user_id'])>3){ //사용자레벨이 게시판 권한설정값보다 작거나 같을시 + $isAuth=true; + } + else{ + if($this->_b_role_cm >= 10){ //게시판 권한설정값이 비회원일시 + $isAuth=true; + } + else{ + $isAuth=false; + } + } + } + + return $isAuth; + } + + /***** + * 게시글 권한 받기 + *****/ + function get_board_auth($argu){ + global $_SESSION; + $ses=$_SESSION; + + $isAuth="E"; + + $data = $this->get_board_view($argu["b_class"], $argu["b_no"]); + + //본인이 쓴 글이나 관리자일 경우 + if(($ses["user_id"]==$data["user_id"] || $ses['user_level']==1 || $ses["user_id"]==$this->_user_id) && isset($ses["user_id"])){ + $isAuth="A"; + } + else{ + if(strlen($argu["board_pwd"])>0){ + if($data["b_pwd"]==get_encrypt_string($argu["board_pwd"]) || $data["user_pwd"]==get_encrypt_string($argu["board_pwd"])){ + $isAuth="A"; + }else{ + $isAuth="F"; + } + }else{ + $isAuth="E"; + } + } + + return $isAuth; + } + + function get_comment_auth($argu,$bcm_gubun,$bcm_no){ + global $_SESSION; + $ses=$_SESSION; + $data = $this->get_comment_view($bcm_gubun,$argu["b_class"], $argu["b_no"],$bcm_no); + + $isAuth="E"; + if(($ses["user_id"] == $data["user_id"] || $ses['user_level']==1 || $ses["user_id"]==$this->_user_id) && isset($ses["user_id"])){ + $isAuth = "A"; + } + else{ + if(strlen($argu["cmt_pwd"])>0){ + if($data["bcm_pwd"]==substr(md5($argu["cmt_pwd"]),0,10)){ + $isAuth="A"; + }else{ + $isAuth="F"; + } + }else{ + $isAuth="E"; + } + } + return $isAuth; + } + + + + function get_board_ramdom($b_class,$limit){ + global $_adminpage,$_agency; + $addwhere = ""; + + if(!$_adminpage) { + /*if($_SESSION['user_level'] != "1"){ + $addwhere .= " and b.b_etc8 = 'Y' "; + }*/ + } + + if(!$_adminpage) $addwhere .= " and b.b_status = 'C'"; + //$addwhere .= " and ('".date("Y-m-d")."' between b.b_etc1 and b.b_etc2) "; + if($b_category) $addwhere .= " and b.b_category = '{$b_category}' "; + + $query = " + select + b.b_class, + b.b_no, + b.b_notice, + b.b_top, + b.b_step, + case b.b_step + when '00' then 0 + else length(b.b_step)/2 + end as b_depth, + b.b_category, + b.b_name, + u.user_name, + b.b_pwd, + b.b_secert, + b.user_id, + if(date_add(b.b_regdate, interval 7 day) > now(),'Y','N') as new, + date_format(b.b_regdate,'%Y-%m-%d') as b_date, + concat('[',date_format(b.b_regdate,'%y-%m-%d'),']') as b_date2, + date_format(b.b_regdate,'%M %d, %Y') as b_date_banner, + date_format(b.b_regdate,'%d %M %Y') as b_date_sub, + date_format(b.b_regdate,'%Y') as b_date_main_y, + date_format(b.b_regdate,'%M') as b_date_main_m, + date_format(b.b_regdate,'%d') as b_date_main_d, + b.b_title, + b.b_tag, + b.b_homepage, + b.b_email, + b.b_mms, + b.b_link, + b.b_summary, + b.b_content, + b.b_ip, + b.b_cnt, + b.a_id, + b.b_status, + b.b_etc1, + b.b_etc2, + b.b_etc3, + b.b_etc4, + b.b_etc5, + b.b_etc6, + b.b_etc7, + b.b_etc8, + b.b_etc9, + b.b_etc10 + from + ".TABLE_BOARD_CONFIG." bc, + ".TABLE_BOARD." b + left outer join ".TABLE_USER." u + on b.user_id = u.user_id + where + b.b_class in ({$b_class}) + and b.b_class= bc.b_class + and b.b_notice <> '1' + $addwhere + order by b.b_notice asc,b.b_top desc, b_step asc + limit ".$limit; + //order by RAND()"; + + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + //debug($res); + //exit; + //go_url("", $res->getMessage()); + return false; + exit; + } + return $list; + } + + } + +?> \ No newline at end of file diff --git a/common/lib/class.cipher.php b/common/lib/class.cipher.php new file mode 100644 index 0000000..4568d7d --- /dev/null +++ b/common/lib/class.cipher.php @@ -0,0 +1,87 @@ +securekey = SECURE_KEY;//hash('sha256',SECURE_KEY,TRUE); + } + + //// 암호화 + function encrypt($sText) { + $cntData = strlen($sText) - 1; + $cntCode = strlen($this->securekey) - 1; + + $arrData = array(); + $arrCode = array(); + + for($i = 0;$cntData >= $i; $i++){ + $arrData[$i] = substr($sText,$i,1); + } + + for($i = 0;$cntCode >= $i; $i++){ + $arrCode[$i] = substr($this->securekey,$i,1); + } + + $flag = 0; + $strResult = ""; + + for($i = 0;$cntData >= $i; $i++){ + + $strResult = $strResult . (ord($arrData[$i]) ^ ord($arrCode[$flag])) . chr(8); + + if($flag == $cntCode){ + $flag = 0; + }else{ + $flag++; + } + } + + return base64_encode($strResult); + } + + /// 복호화 + function decrypt($sText) { + if($sText){ + $sText = base64_decode($sText); + + $arrData = explode(chr(8), $sText); + $arrCode = array(); + + $cntData = count($arrData) - 2; + $cntCode = strlen($this->securekey) - 1; + + for($i = 0; $cntCode >= $i; $i++){ + $arrCode[$i] = substr($this->securekey,$i,1); + } + + $flag = 0; + $strResult = ""; + + for($i = 0;$cntData >= $i; $i++){ + $strResult = $strResult . chr((int)($arrData[$i]) ^ ord($arrCode[$flag])); + + if($flag == $cntCode){ + $flag = 0; + }else{ + $flag++; + } + } + + return $strResult; + }else{ + return null; + } + } +} + +class zm_Cipher_Close{ + function zm_Cipher_Close() { + if( $this->securekey == 0) return; + + $this->securekey = 0; + } +} + +?> \ No newline at end of file diff --git a/common/lib/class.contact.php b/common/lib/class.contact.php new file mode 100644 index 0000000..2e9e1dc --- /dev/null +++ b/common/lib/class.contact.php @@ -0,0 +1,207 @@ +DB = $db; + $this->_PDS .= $this->_PDS_SUB; + } + + /***** + * 등록 + *****/ + function set_insert($argu){ + + global $_adminpage; + +// foreach($_FILES as $fname => $value){ +// if($value[size]>0){ +// $tmp_file="tmp_".$fname; +// $del_file="del_".$fname; +// $path = $this->_PDS; +// $_upload[$fname] = zm_upload($fname, $path, $argu[$del_file], $argu[$tmp_file]); +// } +// } + + $data = array( + "name" => $argu["name"], + "email" => $argu['email'], + "phone" => $argu['phone'], + "type" => $argu['type'], + "space" => $argu['space'], + "addr1" => $argu["addr1"], + "addr2" => $argu["addr2"], + "beginning" => $argu["beginning"], + "budget" => $argu["budget"], + "content" => strip_tags($argu["content"]), + "status" => "N", + "regdate" => _NowTime, + "upfile" => $argu['upfile'], + "upfile_ori" => $argu['upfile_ori'], + ); + + $sth = $this->DB->autoPrepare(TABLE_CONTACT, array_keys($data), DB_AUTOQUERY_INSERT); + $res = $this->DB->execute($sth, array_values($data)); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $id=mysql_insert_id(); + + $data=array_merge($data,array("id"=>$id)); + + return $data; + + } + + /***** + * 수정 + *****/ + function set_modify($argu){ + +// foreach($_FILES as $fname => $value){ +// if($value[size]>0){ +// $tmp_file="tmp_".$fname; +// $del_file="del_".$fname; +// $path = $this->_PDS; +// $_upload[$fname] = zm_upload($fname, $path, $argu[$del_file], $argu[$tmp_file]); +// } +// } + + $data = array( + "name" => $argu["name"], + "email" => $argu['email'], + "phone" => $argu['phone'], + "type" => $argu['type'], + "space" => $argu['space'], + "addr1" => $argu["addr1"], + "addr2" => $argu["addr2"], + "beginning" => $argu["beginning"], + "budget" => $argu["budget"], + "content" => strip_tags($argu["content"]), + "status" => $argu["status"], + ); + + $res = $result = $this->DB->autoExecute(TABLE_CONTACT, $data, + DB_AUTOQUERY_UPDATE, " id = '{$argu['id']}' "); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + /***** + * 삭제. + *****/ + function set_delete($argu){ + + $query = " + delete from ".TABLE_CONTACT." + where id = '{$argu['id']}' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + #리스트 삭제 처리 + function set_delete_list($argu){ + if(count($argu["chk"]) > 0){ + for($i = 0; $i < count($argu["chk"]); $i++){ + $argu["id"] = $argu["chk"][$i]; + $_list = $this -> set_delete($argu); + } + + return true; + } + else{ + go_url("","삭제할데이터가 없습니다."); + exit; + } + } + + + /***** + * 목록을 가져온다. + *****/ + function get_list($argu,&$total,$limit = true){ + + $addwhere = " where (1=1)"; + + /// 검색쿼리 + if($argu['s_string']){ $addwhere .= " and (name like '%{$argu['s_string']}%' or phone like '%{$argu['s_string']}%' or email like '%{$argu['s_string']}%') "; } + + $query = " + select + count(*) + from + ".TABLE_CONTACT." + ".$addwhere; + + $res = $total = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = " + select + * + from + ".TABLE_CONTACT." + ".$addwhere." + order by + regdate desc + "; + if($limit) + $query .= " + limit ".($argu['p']-1)*$this->_LIST_NUM.",".$this->_LIST_NUM; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + /***** + * 정보를 가져온다. + *****/ + function get_view($id){ + + $query = " + select + * + from + ".TABLE_CONTACT." + where + id = '{$id}' + "; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $row; + } +} +?> \ No newline at end of file diff --git a/common/lib/class.history.php b/common/lib/class.history.php new file mode 100644 index 0000000..a20af51 --- /dev/null +++ b/common/lib/class.history.php @@ -0,0 +1,327 @@ +DB = $db; + } + + #등록# + function set_history_insert($argu){ + + + $data = array( + "h_year" => $argu["h_year"], + "h_month" => $argu["h_month"], + "h_regdate" => _NowTime, + "h_gubun" => $argu["h_gubun"], + "division" => $argu["division"] + ); + + $sth = $this->DB->autoPrepare(TABLE_HISTORY, array_keys($data), DB_AUTOQUERY_INSERT); + $res = $this->DB->execute($sth, array_values($data)); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $h_no=mysql_insert_id(); + + $data=array_merge($data,array("h_no"=>$h_no)); + + if(count($argu["h_content"]) > 0){ + for($i=0;$i $data['h_no'], + "h_content" => $argu['h_content'][$i], + ); + + $res = $this->DB->autoExecute(TABLE_HISTORY_LIST, $data_list, DB_AUTOQUERY_INSERT); + if (DB::isError($res)) { + go_url(""," 오류 입니다."); + exit; + } + } + + } + } + + return $data; + + } + + #수정# + function set_history_modify($argu){ + + $data = array( + "h_year" => $argu["h_year"], + "h_month" => $argu["h_month"] + ); + + $res = $result = $this->DB->autoExecute(TABLE_HISTORY, $data, DB_AUTOQUERY_UPDATE, " h_no = '{$argu['h_no']}' "); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + if(count($argu["h_content"]) > 0){ + for($i=0;$i $argu['h_content'][$i] + ); + + $res = $this->DB->autoExecute(TABLE_HISTORY_LIST, $data_list, DB_AUTOQUERY_UPDATE, " hl_no = '{$argu['hl_no'][$i]}' "); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + } + else{ + $data_list = array( + "h_no" => $argu['h_no'], + "h_content" => $argu['h_content'][$i] + ); + + $res = $this->DB->autoExecute(TABLE_HISTORY_LIST, $data_list, DB_AUTOQUERY_INSERT); + if (DB::isError($res)) { + debug($res); + exit; + go_url(""," 오류 입니다."); + exit; + } + } + } + } + + return true; + } + + + #삭제# + function set_history_delete($h_no){ + $query = "DELETE FROM ".TABLE_HISTORY." WHERE h_no = '".$h_no."'"; + + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = "DELETE FROM ".TABLE_HISTORY_LIST." WHERE h_no = '".$h_no."'"; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + function set_history_detail_delete($hl_no){ + $query = "DELETE FROM ".TABLE_HISTORY_LIST." WHERE hl_no = '".$hl_no."'"; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + + #리스트삭제# + function set_history_delete_list($argu){ + if(count($argu["chk"]) > 0){ + for($i = 0; $i < count($argu["chk"]); $i++){ + $h_no = $argu["chk"][$i]; + $_list = $this -> set_history_delete($h_no); + } + return true; + } + else{ + go_url("","삭제할데이터가 없습니다."); + exit; + } + } + + + #리스트# + function get_history_list($argu,&$total,$limit = true){ + $addwhere = " where (1=1) and (h_gubun = '".$argu["h_gubun"]."') and (division = '".$argu["division"]."')"; + + /// 검색쿼리 + if($argu['h_year']){ $addwhere .= " and h_year like '{$argu['h_year']}%' "; } + if($argu['s_string']){ $addwhere .= " and h_content like '%{$argu['s_string']}%' "; } + + $query = " + select + count(*) + from + ".TABLE_HISTORY." + ".$addwhere; + + $res = $total = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = " + select + *, + date_format(STR_TO_DATE(h_month,'%m'),'%M') as h_month_m + from + ".TABLE_HISTORY." + ".$addwhere." + order by + CONVERT(h_year, UNSIGNED) desc, CONVERT(h_month, UNSIGNED) desc, h_no desc + "; + if($limit) + $query .= " + limit ".($argu['p']-1)*$this->_LIST_NUM.",".$this->_LIST_NUM; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + + } + + function get_histroy_detail($h_no){ + $addwhere = "where h_no = '".$h_no."'"; + $query = " + select + * + from + ".TABLE_HISTORY_LIST." + ".$addwhere." + order by + hl_no asc + "; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + + #상세보기 + function get_history_view($h_no){ + $query = "SELECT + * + FROM ".TABLE_HISTORY." + where h_no = '".$h_no."'"; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $row; + + } + + + #메인리스트# + function get_main_history($h_no){ + + $addwhere = "WHERE (1=1) and (h_gubun = '".$argu["h_gubun"]."')"; + $addwhere .= " AND (h_no = '{$h_no}')"; + + $query = "SELECT + * + FROM ".TABLE_HISTORY_LIST." + ".$addwhere." + ORDER BY hl_no asc"; + + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + #메인리스트# + function get_main_year($argu){ + $addwhere = "WHERE (1=1) and (h_gubun = '".$argu["h_gubun"]."') and (division = '".$argu["division"]."')"; + + $query = "SELECT + DISTINCT h_year, + h_no + FROM ".TABLE_HISTORY." + ".$addwhere." + ORDER BY h_year desc"; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + function get_main_year1($argu){ + $addwhere = "WHERE (1=1) and (h_gubun = '".$argu["h_gubun"]."') and (division = '".$argu["division"]."')"; + + $query = "SELECT + * + FROM ".TABLE_HISTORY." + ".$addwhere." + ORDER BY CONVERT(h_year, UNSIGNED) desc, CONVERT(h_month, UNSIGNED) desc, h_no desc"; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + function get_main_month($h_year,$h_gubun){ + + + $query = "SELECT + h_no, + substr(date_format(STR_TO_DATE(h_month,'%m'),'%M'),1,3) as h_month_txt + FROM ".TABLE_HISTORY." + WHERE (h_year = '{$h_year}') and (h_gubun = '".$h_gubun."') + ORDER BY CONVERT(h_month, UNSIGNED) desc"; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + } +?> \ No newline at end of file diff --git a/common/lib/class.phpmailer.php b/common/lib/class.phpmailer.php new file mode 100644 index 0000000..2c8b339 --- /dev/null +++ b/common/lib/class.phpmailer.php @@ -0,0 +1,3894 @@ + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2012 - 2014 Marcus Bointon + * @copyright 2010 - 2012 Jim Jagielski + * @copyright 2004 - 2009 Andy Prevost + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * PHPMailer - PHP email creation and transport class. + * @package PHPMailer + * @author Marcus Bointon (Synchro/coolbru) + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + */ +class PHPMailer +{ + /** + * The PHPMailer Version number. + * @var string + */ + public $Version = '5.2.14'; + + /** + * Email priority. + * Options: null (default), 1 = High, 3 = Normal, 5 = low. + * When null, the header is not set at all. + * @var integer + */ + public $Priority = null; + + /** + * The character set of the message. + * @var string + */ + public $CharSet = 'iso-8859-1'; + + /** + * The MIME Content-type of the message. + * @var string + */ + public $ContentType = 'text/plain'; + + /** + * The message encoding. + * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable". + * @var string + */ + public $Encoding = '8bit'; + + /** + * Holds the most recent mailer error message. + * @var string + */ + public $ErrorInfo = ''; + + /** + * The From email address for the message. + * @var string + */ + public $From = 'root@localhost'; + + /** + * The From name of the message. + * @var string + */ + public $FromName = 'Root User'; + + /** + * The Sender email (Return-Path) of the message. + * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode. + * @var string + */ + public $Sender = ''; + + /** + * The Return-Path of the message. + * If empty, it will be set to either From or Sender. + * @var string + * @deprecated Email senders should never set a return-path header; + * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything. + * @link https://tools.ietf.org/html/rfc5321#section-4.4 RFC5321 reference + */ + public $ReturnPath = ''; + + /** + * The Subject of the message. + * @var string + */ + public $Subject = ''; + + /** + * An HTML or plain text message body. + * If HTML then call isHTML(true). + * @var string + */ + public $Body = ''; + + /** + * The plain-text message body. + * This body can be read by mail clients that do not have HTML email + * capability such as mutt & Eudora. + * Clients that can read HTML will view the normal Body. + * @var string + */ + public $AltBody = ''; + + /** + * An iCal message part body. + * Only supported in simple alt or alt_inline message types + * To generate iCal events, use the bundled extras/EasyPeasyICS.php class or iCalcreator + * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/ + * @link http://kigkonsult.se/iCalcreator/ + * @var string + */ + public $Ical = ''; + + /** + * The complete compiled MIME message body. + * @access protected + * @var string + */ + protected $MIMEBody = ''; + + /** + * The complete compiled MIME message headers. + * @var string + * @access protected + */ + protected $MIMEHeader = ''; + + /** + * Extra headers that createHeader() doesn't fold in. + * @var string + * @access protected + */ + protected $mailHeader = ''; + + /** + * Word-wrap the message body to this number of chars. + * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance. + * @var integer + */ + public $WordWrap = 0; + + /** + * Which method to use to send mail. + * Options: "mail", "sendmail", or "smtp". + * @var string + */ + public $Mailer = 'mail'; + + /** + * The path to the sendmail program. + * @var string + */ + public $Sendmail = '/usr/sbin/sendmail'; + + /** + * Whether mail() uses a fully sendmail-compatible MTA. + * One which supports sendmail's "-oi -f" options. + * @var boolean + */ + public $UseSendmailOptions = true; + + /** + * Path to PHPMailer plugins. + * Useful if the SMTP class is not in the PHP include path. + * @var string + * @deprecated Should not be needed now there is an autoloader. + */ + public $PluginDir = ''; + + /** + * The email address that a reading confirmation should be sent to, also known as read receipt. + * @var string + */ + public $ConfirmReadingTo = ''; + + /** + * The hostname to use in the Message-ID header and as default HELO string. + * If empty, PHPMailer attempts to find one with, in order, + * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value + * 'localhost.localdomain'. + * @var string + */ + public $Hostname = ''; + + /** + * An ID to be used in the Message-ID header. + * If empty, a unique id will be generated. + * @var string + */ + public $MessageID = ''; + + /** + * The message Date to be used in the Date header. + * If empty, the current date will be added. + * @var string + */ + public $MessageDate = ''; + + /** + * SMTP hosts. + * Either a single hostname or multiple semicolon-delimited hostnames. + * You can also specify a different port + * for each host by using this format: [hostname:port] + * (e.g. "smtp1.example.com:25;smtp2.example.com"). + * You can also specify encryption type, for example: + * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465"). + * Hosts will be tried in order. + * @var string + */ + public $Host = 'localhost'; + + /** + * The default SMTP server port. + * @var integer + * @TODO Why is this needed when the SMTP class takes care of it? + */ + public $Port = 25; + + /** + * The SMTP HELO of the message. + * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find + * one with the same method described above for $Hostname. + * @var string + * @see PHPMailer::$Hostname + */ + public $Helo = ''; + + /** + * What kind of encryption to use on the SMTP connection. + * Options: '', 'ssl' or 'tls' + * @var string + */ + public $SMTPSecure = ''; + + /** + * Whether to enable TLS encryption automatically if a server supports it, + * even if `SMTPSecure` is not set to 'tls'. + * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid. + * @var boolean + */ + public $SMTPAutoTLS = true; + + /** + * Whether to use SMTP authentication. + * Uses the Username and Password properties. + * @var boolean + * @see PHPMailer::$Username + * @see PHPMailer::$Password + */ + public $SMTPAuth = false; + + /** + * Options array passed to stream_context_create when connecting via SMTP. + * @var array + */ + public $SMTPOptions = array(); + + /** + * SMTP username. + * @var string + */ + public $Username = ''; + + /** + * SMTP password. + * @var string + */ + public $Password = ''; + + /** + * SMTP auth type. + * Options are LOGIN (default), PLAIN, NTLM, CRAM-MD5 + * @var string + */ + public $AuthType = ''; + + /** + * SMTP realm. + * Used for NTLM auth + * @var string + */ + public $Realm = ''; + + /** + * SMTP workstation. + * Used for NTLM auth + * @var string + */ + public $Workstation = ''; + + /** + * The SMTP server timeout in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * @var integer + */ + public $Timeout = 300; + + /** + * SMTP class debug output mode. + * Debug output level. + * Options: + * * `0` No output + * * `1` Commands + * * `2` Data and commands + * * `3` As 2 plus connection status + * * `4` Low-level data output + * @var integer + * @see SMTP::$do_debug + */ + public $SMTPDebug = 0; + + /** + * How to handle debug output. + * Options: + * * `echo` Output plain-text as-is, appropriate for CLI + * * `html` Output escaped, line breaks converted to `
`, appropriate for browser output + * * `error_log` Output to error log as configured in php.ini + * + * Alternatively, you can provide a callable expecting two params: a message string and the debug level: + * + * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; + * + * @var string|callable + * @see SMTP::$Debugoutput + */ + public $Debugoutput = 'echo'; + + /** + * Whether to keep SMTP connection open after each message. + * If this is set to true then to close the connection + * requires an explicit call to smtpClose(). + * @var boolean + */ + public $SMTPKeepAlive = false; + + /** + * Whether to split multiple to addresses into multiple messages + * or send them all in one message. + * Only supported in `mail` and `sendmail` transports, not in SMTP. + * @var boolean + */ + public $SingleTo = false; + + /** + * Storage for addresses when SingleTo is enabled. + * @var array + * @TODO This should really not be public + */ + public $SingleToArray = array(); + + /** + * Whether to generate VERP addresses on send. + * Only applicable when sending via SMTP. + * @link https://en.wikipedia.org/wiki/Variable_envelope_return_path + * @link http://www.postfix.org/VERP_README.html Postfix VERP info + * @var boolean + */ + public $do_verp = false; + + /** + * Whether to allow sending messages with an empty body. + * @var boolean + */ + public $AllowEmpty = false; + + /** + * The default line ending. + * @note The default remains "\n". We force CRLF where we know + * it must be used via self::CRLF. + * @var string + */ + public $LE = "\n"; + + /** + * DKIM selector. + * @var string + */ + public $DKIM_selector = ''; + + /** + * DKIM Identity. + * Usually the email address used as the source of the email + * @var string + */ + public $DKIM_identity = ''; + + /** + * DKIM passphrase. + * Used if your key is encrypted. + * @var string + */ + public $DKIM_passphrase = ''; + + /** + * DKIM signing domain name. + * @example 'example.com' + * @var string + */ + public $DKIM_domain = ''; + + /** + * DKIM private key file path. + * @var string + */ + public $DKIM_private = ''; + + /** + * Callback Action function name. + * + * The function that handles the result of the send email action. + * It is called out by send() for each email sent. + * + * Value can be any php callable: http://www.php.net/is_callable + * + * Parameters: + * boolean $result result of the send action + * string $to email address of the recipient + * string $cc cc email addresses + * string $bcc bcc email addresses + * string $subject the subject + * string $body the email body + * string $from email address of sender + * @var string + */ + public $action_function = ''; + + /** + * What to put in the X-Mailer header. + * Options: An empty string for PHPMailer default, whitespace for none, or a string to use + * @var string + */ + public $XMailer = ''; + + /** + * An instance of the SMTP sender class. + * @var SMTP + * @access protected + */ + protected $smtp = null; + + /** + * The array of 'to' names and addresses. + * @var array + * @access protected + */ + protected $to = array(); + + /** + * The array of 'cc' names and addresses. + * @var array + * @access protected + */ + protected $cc = array(); + + /** + * The array of 'bcc' names and addresses. + * @var array + * @access protected + */ + protected $bcc = array(); + + /** + * The array of reply-to names and addresses. + * @var array + * @access protected + */ + protected $ReplyTo = array(); + + /** + * An array of all kinds of addresses. + * Includes all of $to, $cc, $bcc + * @var array + * @access protected + * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc + */ + protected $all_recipients = array(); + + /** + * An array of names and addresses queued for validation. + * In send(), valid and non duplicate entries are moved to $all_recipients + * and one of $to, $cc, or $bcc. + * This array is used only for addresses with IDN. + * @var array + * @access protected + * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc + * @see PHPMailer::$all_recipients + */ + protected $RecipientsQueue = array(); + + /** + * An array of reply-to names and addresses queued for validation. + * In send(), valid and non duplicate entries are moved to $ReplyTo. + * This array is used only for addresses with IDN. + * @var array + * @access protected + * @see PHPMailer::$ReplyTo + */ + protected $ReplyToQueue = array(); + + /** + * The array of attachments. + * @var array + * @access protected + */ + protected $attachment = array(); + + /** + * The array of custom headers. + * @var array + * @access protected + */ + protected $CustomHeader = array(); + + /** + * The most recent Message-ID (including angular brackets). + * @var string + * @access protected + */ + protected $lastMessageID = ''; + + /** + * The message's MIME type. + * @var string + * @access protected + */ + protected $message_type = ''; + + /** + * The array of MIME boundary strings. + * @var array + * @access protected + */ + protected $boundary = array(); + + /** + * The array of available languages. + * @var array + * @access protected + */ + protected $language = array(); + + /** + * The number of errors encountered. + * @var integer + * @access protected + */ + protected $error_count = 0; + + /** + * The S/MIME certificate file path. + * @var string + * @access protected + */ + protected $sign_cert_file = ''; + + /** + * The S/MIME key file path. + * @var string + * @access protected + */ + protected $sign_key_file = ''; + + /** + * The optional S/MIME extra certificates ("CA Chain") file path. + * @var string + * @access protected + */ + protected $sign_extracerts_file = ''; + + /** + * The S/MIME password for the key. + * Used only if the key is encrypted. + * @var string + * @access protected + */ + protected $sign_key_pass = ''; + + /** + * Whether to throw exceptions for errors. + * @var boolean + * @access protected + */ + protected $exceptions = false; + + /** + * Unique ID used for message ID and boundaries. + * @var string + * @access protected + */ + protected $uniqueid = ''; + + /** + * Error severity: message only, continue processing. + */ + const STOP_MESSAGE = 0; + + /** + * Error severity: message, likely ok to continue processing. + */ + const STOP_CONTINUE = 1; + + /** + * Error severity: message, plus full stop, critical error reached. + */ + const STOP_CRITICAL = 2; + + /** + * SMTP RFC standard line ending. + */ + const CRLF = "\r\n"; + + /** + * The maximum line length allowed by RFC 2822 section 2.1.1 + * @var integer + */ + const MAX_LINE_LENGTH = 998; + + /** + * Constructor. + * @param boolean $exceptions Should we throw external exceptions? + */ + public function __construct($exceptions = null) + { + if ($exceptions !== null) { + $this->exceptions = (boolean)$exceptions; + } + } + + /** + * Destructor. + */ + public function __destruct() + { + //Close any open SMTP connection nicely + $this->smtpClose(); + } + + /** + * Call mail() in a safe_mode-aware fashion. + * Also, unless sendmail_path points to sendmail (or something that + * claims to be sendmail), don't pass params (not a perfect fix, + * but it will do) + * @param string $to To + * @param string $subject Subject + * @param string $body Message Body + * @param string $header Additional Header(s) + * @param string $params Params + * @access private + * @return boolean + */ + private function mailPassthru($to, $subject, $body, $header, $params) + { + //Check overloading of mail function to avoid double-encoding + if (ini_get('mbstring.func_overload') & 1) { + $subject = $this->secureHeader($subject); + } else { + $subject = $this->encodeHeader($this->secureHeader($subject)); + } + if (ini_get('safe_mode') || !($this->UseSendmailOptions)) { + $result = @mail($to, $subject, $body, $header); + } else { + $result = @mail($to, $subject, $body, $header, $params); + } + return $result; + } + + /** + * Output debugging info via user-defined method. + * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug). + * @see PHPMailer::$Debugoutput + * @see PHPMailer::$SMTPDebug + * @param string $str + */ + protected function edebug($str) + { + if ($this->SMTPDebug <= 0) { + return; + } + //Avoid clash with built-in function names + if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) { + call_user_func($this->Debugoutput, $str, $this->SMTPDebug); + return; + } + switch ($this->Debugoutput) { + case 'error_log': + //Don't output, just log + error_log($str); + break; + case 'html': + //Cleans up output a bit for a better looking, HTML-safe output + echo htmlentities( + preg_replace('/[\r\n]+/', '', $str), + ENT_QUOTES, + 'UTF-8' + ) + . "
\n"; + break; + case 'echo': + default: + //Normalize line breaks + $str = preg_replace('/\r\n?/ms', "\n", $str); + echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( + "\n", + "\n \t ", + trim($str) + ) . "\n"; + } + } + + /** + * Sets message type to HTML or plain. + * @param boolean $isHtml True for HTML mode. + * @return void + */ + public function isHTML($isHtml = true) + { + if ($isHtml) { + $this->ContentType = 'text/html'; + } else { + $this->ContentType = 'text/plain'; + } + } + + /** + * Send messages using SMTP. + * @return void + */ + public function isSMTP() + { + $this->Mailer = 'smtp'; + } + + /** + * Send messages using PHP's mail() function. + * @return void + */ + public function isMail() + { + $this->Mailer = 'mail'; + } + + /** + * Send messages using $Sendmail. + * @return void + */ + public function isSendmail() + { + $ini_sendmail_path = ini_get('sendmail_path'); + + if (!stristr($ini_sendmail_path, 'sendmail')) { + $this->Sendmail = '/usr/sbin/sendmail'; + } else { + $this->Sendmail = $ini_sendmail_path; + } + $this->Mailer = 'sendmail'; + } + + /** + * Send messages using qmail. + * @return void + */ + public function isQmail() + { + $ini_sendmail_path = ini_get('sendmail_path'); + + if (!stristr($ini_sendmail_path, 'qmail')) { + $this->Sendmail = '/var/qmail/bin/qmail-inject'; + } else { + $this->Sendmail = $ini_sendmail_path; + } + $this->Mailer = 'qmail'; + } + + /** + * Add a "To" address. + * @param string $address The email address to send to + * @param string $name + * @return boolean true on success, false if address already used or invalid in some way + */ + public function addAddress($address, $name = '') + { + return $this->addOrEnqueueAnAddress('to', $address, $name); + } + + /** + * Add a "CC" address. + * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. + * @param string $address The email address to send to + * @param string $name + * @return boolean true on success, false if address already used or invalid in some way + */ + public function addCC($address, $name = '') + { + return $this->addOrEnqueueAnAddress('cc', $address, $name); + } + + /** + * Add a "BCC" address. + * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer. + * @param string $address The email address to send to + * @param string $name + * @return boolean true on success, false if address already used or invalid in some way + */ + public function addBCC($address, $name = '') + { + return $this->addOrEnqueueAnAddress('bcc', $address, $name); + } + + /** + * Add a "Reply-To" address. + * @param string $address The email address to reply to + * @param string $name + * @return boolean true on success, false if address already used or invalid in some way + */ + public function addReplyTo($address, $name = '') + { + return $this->addOrEnqueueAnAddress('Reply-To', $address, $name); + } + + /** + * Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer + * can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still + * be modified after calling this function), addition of such addresses is delayed until send(). + * Addresses that have been added already return false, but do not throw exceptions. + * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' + * @param string $address The email address to send, resp. to reply to + * @param string $name + * @throws phpmailerException + * @return boolean true on success, false if address already used or invalid in some way + * @access protected + */ + protected function addOrEnqueueAnAddress($kind, $address, $name) + { + $address = trim($address); + $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim + if (($pos = strrpos($address, '@')) === false) { + // At-sign is misssing. + $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address"; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + $params = array($kind, $address, $name); + // Enqueue addresses with IDN until we know the PHPMailer::$CharSet. + if ($this->has8bitChars(substr($address, ++$pos)) and $this->idnSupported()) { + if ($kind != 'Reply-To') { + if (!array_key_exists($address, $this->RecipientsQueue)) { + $this->RecipientsQueue[$address] = $params; + return true; + } + } else { + if (!array_key_exists($address, $this->ReplyToQueue)) { + $this->ReplyToQueue[$address] = $params; + return true; + } + } + return false; + } + // Immediately add standard addresses without IDN. + return call_user_func_array(array($this, 'addAnAddress'), $params); + } + + /** + * Add an address to one of the recipient arrays or to the ReplyTo array. + * Addresses that have been added already return false, but do not throw exceptions. + * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' + * @param string $address The email address to send, resp. to reply to + * @param string $name + * @throws phpmailerException + * @return boolean true on success, false if address already used or invalid in some way + * @access protected + */ + protected function addAnAddress($kind, $address, $name = '') + { + if (!in_array($kind, array('to', 'cc', 'bcc', 'Reply-To'))) { + $error_message = $this->lang('Invalid recipient kind: ') . $kind; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + if (!$this->validateAddress($address)) { + $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address"; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + if ($kind != 'Reply-To') { + if (!array_key_exists(strtolower($address), $this->all_recipients)) { + array_push($this->$kind, array($address, $name)); + $this->all_recipients[strtolower($address)] = true; + return true; + } + } else { + if (!array_key_exists(strtolower($address), $this->ReplyTo)) { + $this->ReplyTo[strtolower($address)] = array($address, $name); + return true; + } + } + return false; + } + + /** + * Parse and validate a string containing one or more RFC822-style comma-separated email addresses + * of the form "display name
" into an array of name/address pairs. + * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available. + * Note that quotes in the name part are removed. + * @param string $addrstr The address list string + * @param bool $useimap Whether to use the IMAP extension to parse the list + * @return array + * @link http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation + */ + public function parseAddresses($addrstr, $useimap = true) + { + $addresses = array(); + if ($useimap and function_exists('imap_rfc822_parse_adrlist')) { + //Use this built-in parser if it's available + $list = imap_rfc822_parse_adrlist($addrstr, ''); + foreach ($list as $address) { + if ($address->host != '.SYNTAX-ERROR.') { + if ($this->validateAddress($address->mailbox . '@' . $address->host)) { + $addresses[] = array( + 'name' => (property_exists($address, 'personal') ? $address->personal : ''), + 'address' => $address->mailbox . '@' . $address->host + ); + } + } + } + } else { + //Use this simpler parser + $list = explode(',', $addrstr); + foreach ($list as $address) { + $address = trim($address); + //Is there a separate name part? + if (strpos($address, '<') === false) { + //No separate name, just use the whole thing + if ($this->validateAddress($address)) { + $addresses[] = array( + 'name' => '', + 'address' => $address + ); + } + } else { + list($name, $email) = explode('<', $address); + $email = trim(str_replace('>', '', $email)); + if ($this->validateAddress($email)) { + $addresses[] = array( + 'name' => trim(str_replace(array('"', "'"), '', $name)), + 'address' => $email + ); + } + } + } + } + return $addresses; + } + + /** + * Set the From and FromName properties. + * @param string $address + * @param string $name + * @param boolean $auto Whether to also set the Sender address, defaults to true + * @throws phpmailerException + * @return boolean + */ + public function setFrom($address, $name = '', $auto = true) + { + $address = trim($address); + $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim + // Don't validate now addresses with IDN. Will be done in send(). + if (($pos = strrpos($address, '@')) === false or + (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and + !$this->validateAddress($address)) { + $error_message = $this->lang('invalid_address') . " (setFrom) $address"; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + $this->From = $address; + $this->FromName = $name; + if ($auto) { + if (empty($this->Sender)) { + $this->Sender = $address; + } + } + return true; + } + + /** + * Return the Message-ID header of the last email. + * Technically this is the value from the last time the headers were created, + * but it's also the message ID of the last sent message except in + * pathological cases. + * @return string + */ + public function getLastMessageID() + { + return $this->lastMessageID; + } + + /** + * Check that a string looks like an email address. + * @param string $address The email address to check + * @param string $patternselect A selector for the validation pattern to use : + * * `auto` Pick best pattern automatically; + * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14; + * * `pcre` Use old PCRE implementation; + * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; + * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. + * * `noregex` Don't use a regex: super fast, really dumb. + * @return boolean + * @static + * @access public + */ + public static function validateAddress($address, $patternselect = 'auto') + { + //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321 + if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) { + return false; + } + if (!$patternselect or $patternselect == 'auto') { + //Check this constant first so it works when extension_loaded() is disabled by safe mode + //Constant was added in PHP 5.2.4 + if (defined('PCRE_VERSION')) { + //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2 + if (version_compare(PCRE_VERSION, '8.0.3') >= 0) { + $patternselect = 'pcre8'; + } else { + $patternselect = 'pcre'; + } + } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) { + //Fall back to older PCRE + $patternselect = 'pcre'; + } else { + //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension + if (version_compare(PHP_VERSION, '5.2.0') >= 0) { + $patternselect = 'php'; + } else { + $patternselect = 'noregex'; + } + } + } + switch ($patternselect) { + case 'pcre8': + /** + * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains. + * @link http://squiloople.com/2009/12/20/email-address-validation/ + * @copyright 2009-2010 Michael Rushton + * Feel free to use and redistribute this code. But please keep this copyright notice. + */ + return (boolean)preg_match( + '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' . + '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' . + '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' . + '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' . + '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' . + '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' . + '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' . + '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' . + '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', + $address + ); + case 'pcre': + //An older regex that doesn't need a recent PCRE + return (boolean)preg_match( + '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' . + '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' . + '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' . + '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' . + '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' . + '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' . + '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' . + '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' . + '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' . + '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD', + $address + ); + case 'html5': + /** + * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements. + * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email) + */ + return (boolean)preg_match( + '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' . + '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD', + $address + ); + case 'noregex': + //No PCRE! Do something _very_ approximate! + //Check the address is 3 chars or longer and contains an @ that's not the first or last char + return (strlen($address) >= 3 + and strpos($address, '@') >= 1 + and strpos($address, '@') != strlen($address) - 1); + case 'php': + default: + return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL); + } + } + + /** + * Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the + * "intl" and "mbstring" PHP extensions. + * @return bool "true" if required functions for IDN support are present + */ + public function idnSupported() + { + // @TODO: Write our own "idn_to_ascii" function for PHP <= 5.2. + return function_exists('idn_to_ascii') and function_exists('mb_convert_encoding'); + } + + /** + * Converts IDN in given email address to its ASCII form, also known as punycode, if possible. + * Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet. + * This function silently returns unmodified address if: + * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form) + * - Conversion to punycode is impossible (e.g. required PHP functions are not available) + * or fails for any reason (e.g. domain has characters not allowed in an IDN) + * @see PHPMailer::$CharSet + * @param string $address The email address to convert + * @return string The encoded address in ASCII form + */ + public function punyencodeAddress($address) + { + // Verify we have required functions, CharSet, and at-sign. + if ($this->idnSupported() and + !empty($this->CharSet) and + ($pos = strrpos($address, '@')) !== false) { + $domain = substr($address, ++$pos); + // Verify CharSet string is a valid one, and domain properly encoded in this CharSet. + if ($this->has8bitChars($domain) and @mb_check_encoding($domain, $this->CharSet)) { + $domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet); + if (($punycode = defined('INTL_IDNA_VARIANT_UTS46') ? + idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46) : + idn_to_ascii($domain)) !== false) { + return substr($address, 0, $pos) . $punycode; + } + } + } + return $address; + } + + /** + * Create a message and send it. + * Uses the sending method specified by $Mailer. + * @throws phpmailerException + * @return boolean false on error - See the ErrorInfo property for details of the error. + */ + public function send() + { + try { + if (!$this->preSend()) { + return false; + } + return $this->postSend(); + } catch (phpmailerException $exc) { + $this->mailHeader = ''; + $this->setError($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + return false; + } + } + + /** + * Prepare a message for sending. + * @throws phpmailerException + * @return boolean + */ + public function preSend() + { + try { + $this->error_count = 0; // Reset errors + $this->mailHeader = ''; + + // Dequeue recipient and Reply-To addresses with IDN + foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) { + $params[1] = $this->punyencodeAddress($params[1]); + call_user_func_array(array($this, 'addAnAddress'), $params); + } + if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) { + throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL); + } + + // Validate From, Sender, and ConfirmReadingTo addresses + foreach (array('From', 'Sender', 'ConfirmReadingTo') as $address_kind) { + $this->$address_kind = trim($this->$address_kind); + if (empty($this->$address_kind)) { + continue; + } + $this->$address_kind = $this->punyencodeAddress($this->$address_kind); + if (!$this->validateAddress($this->$address_kind)) { + $error_message = $this->lang('invalid_address') . ' (punyEncode) ' . $this->$address_kind; + $this->setError($error_message); + $this->edebug($error_message); + if ($this->exceptions) { + throw new phpmailerException($error_message); + } + return false; + } + } + + // Set whether the message is multipart/alternative + if ($this->alternativeExists()) { + $this->ContentType = 'multipart/alternative'; + } + + $this->setMessageType(); + // Refuse to send an empty message unless we are specifically allowing it + if (!$this->AllowEmpty and empty($this->Body)) { + throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL); + } + + // Create body before headers in case body makes changes to headers (e.g. altering transfer encoding) + $this->MIMEHeader = ''; + $this->MIMEBody = $this->createBody(); + // createBody may have added some headers, so retain them + $tempheaders = $this->MIMEHeader; + $this->MIMEHeader = $this->createHeader(); + $this->MIMEHeader .= $tempheaders; + + // To capture the complete message when using mail(), create + // an extra header list which createHeader() doesn't fold in + if ($this->Mailer == 'mail') { + if (count($this->to) > 0) { + $this->mailHeader .= $this->addrAppend('To', $this->to); + } else { + $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;'); + } + $this->mailHeader .= $this->headerLine( + 'Subject', + $this->encodeHeader($this->secureHeader(trim($this->Subject))) + ); + } + + // Sign with DKIM if enabled + if (!empty($this->DKIM_domain) + && !empty($this->DKIM_private) + && !empty($this->DKIM_selector) + && file_exists($this->DKIM_private)) { + $header_dkim = $this->DKIM_Add( + $this->MIMEHeader . $this->mailHeader, + $this->encodeHeader($this->secureHeader($this->Subject)), + $this->MIMEBody + ); + $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF . + str_replace("\r\n", "\n", $header_dkim) . self::CRLF; + } + return true; + } catch (phpmailerException $exc) { + $this->setError($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + return false; + } + } + + /** + * Actually send a message. + * Send the email via the selected mechanism + * @throws phpmailerException + * @return boolean + */ + public function postSend() + { + try { + // Choose the mailer and send through it + switch ($this->Mailer) { + case 'sendmail': + case 'qmail': + return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody); + case 'smtp': + return $this->smtpSend($this->MIMEHeader, $this->MIMEBody); + case 'mail': + return $this->mailSend($this->MIMEHeader, $this->MIMEBody); + default: + $sendMethod = $this->Mailer.'Send'; + if (method_exists($this, $sendMethod)) { + return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody); + } + + return $this->mailSend($this->MIMEHeader, $this->MIMEBody); + } + } catch (phpmailerException $exc) { + $this->setError($exc->getMessage()); + $this->edebug($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + } + return false; + } + + /** + * Send mail using the $Sendmail program. + * @param string $header The message headers + * @param string $body The message body + * @see PHPMailer::$Sendmail + * @throws phpmailerException + * @access protected + * @return boolean + */ + protected function sendmailSend($header, $body) + { + if ($this->Sender != '') { + if ($this->Mailer == 'qmail') { + $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + } else { + $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender)); + } + } else { + if ($this->Mailer == 'qmail') { + $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail)); + } else { + $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail)); + } + } + if ($this->SingleTo) { + foreach ($this->SingleToArray as $toAddr) { + if (!@$mail = popen($sendmail, 'w')) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + fputs($mail, 'To: ' . $toAddr . "\n"); + fputs($mail, $header); + fputs($mail, $body); + $result = pclose($mail); + $this->doCallback( + ($result == 0), + array($toAddr), + $this->cc, + $this->bcc, + $this->Subject, + $body, + $this->From + ); + if ($result != 0) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + } + } else { + if (!@$mail = popen($sendmail, 'w')) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + fputs($mail, $header); + fputs($mail, $body); + $result = pclose($mail); + $this->doCallback( + ($result == 0), + $this->to, + $this->cc, + $this->bcc, + $this->Subject, + $body, + $this->From + ); + if ($result != 0) { + throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); + } + } + return true; + } + + /** + * Send mail using the PHP mail() function. + * @param string $header The message headers + * @param string $body The message body + * @link http://www.php.net/manual/en/book.mail.php + * @throws phpmailerException + * @access protected + * @return boolean + */ + protected function mailSend($header, $body) + { + $toArr = array(); + foreach ($this->to as $toaddr) { + $toArr[] = $this->addrFormat($toaddr); + } + $to = implode(', ', $toArr); + + if (empty($this->Sender)) { + $params = ' '; + } else { + $params = sprintf('-f%s', $this->Sender); + } + if ($this->Sender != '' and !ini_get('safe_mode')) { + $old_from = ini_get('sendmail_from'); + ini_set('sendmail_from', $this->Sender); + } + $result = false; + if ($this->SingleTo && count($toArr) > 1) { + foreach ($toArr as $toAddr) { + $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); + $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From); + } + } else { + $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params); + $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From); + } + if (isset($old_from)) { + ini_set('sendmail_from', $old_from); + } + if (!$result) { + throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL); + } + return true; + } + + /** + * Get an instance to use for SMTP operations. + * Override this function to load your own SMTP implementation + * @return SMTP + */ + public function getSMTPInstance() + { + if (!is_object($this->smtp)) { + $this->smtp = new SMTP; + } + return $this->smtp; + } + + /** + * Send mail via SMTP. + * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. + * Uses the PHPMailerSMTP class by default. + * @see PHPMailer::getSMTPInstance() to use a different class. + * @param string $header The message headers + * @param string $body The message body + * @throws phpmailerException + * @uses SMTP + * @access protected + * @return boolean + */ + protected function smtpSend($header, $body) + { + $bad_rcpt = array(); + if (!$this->smtpConnect($this->SMTPOptions)) { + throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL); + } + if ('' == $this->Sender) { + $smtp_from = $this->From; + } else { + $smtp_from = $this->Sender; + } + if (!$this->smtp->mail($smtp_from)) { + $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError())); + throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL); + } + + // Attempt to send to all recipients + foreach (array($this->to, $this->cc, $this->bcc) as $togroup) { + foreach ($togroup as $to) { + if (!$this->smtp->recipient($to[0])) { + $error = $this->smtp->getError(); + $bad_rcpt[] = array('to' => $to[0], 'error' => $error['detail']); + $isSent = false; + } else { + $isSent = true; + } + $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From); + } + } + + // Only send the DATA command if we have viable recipients + if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) { + throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL); + } + if ($this->SMTPKeepAlive) { + $this->smtp->reset(); + } else { + $this->smtp->quit(); + $this->smtp->close(); + } + //Create error message for any bad addresses + if (count($bad_rcpt) > 0) { + $errstr = ''; + foreach ($bad_rcpt as $bad) { + $errstr .= $bad['to'] . ': ' . $bad['error']; + } + throw new phpmailerException( + $this->lang('recipients_failed') . $errstr, + self::STOP_CONTINUE + ); + } + return true; + } + + /** + * Initiate a connection to an SMTP server. + * Returns false if the operation failed. + * @param array $options An array of options compatible with stream_context_create() + * @uses SMTP + * @access public + * @throws phpmailerException + * @return boolean + */ + public function smtpConnect($options = array()) + { + if (is_null($this->smtp)) { + $this->smtp = $this->getSMTPInstance(); + } + + // Already connected? + if ($this->smtp->connected()) { + return true; + } + + $this->smtp->setTimeout($this->Timeout); + $this->smtp->setDebugLevel($this->SMTPDebug); + $this->smtp->setDebugOutput($this->Debugoutput); + $this->smtp->setVerp($this->do_verp); + $hosts = explode(';', $this->Host); + $lastexception = null; + + foreach ($hosts as $hostentry) { + $hostinfo = array(); + if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) { + // Not a valid host entry + continue; + } + // $hostinfo[2]: optional ssl or tls prefix + // $hostinfo[3]: the hostname + // $hostinfo[4]: optional port number + // The host string prefix can temporarily override the current setting for SMTPSecure + // If it's not specified, the default value is used + $prefix = ''; + $secure = $this->SMTPSecure; + $tls = ($this->SMTPSecure == 'tls'); + if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) { + $prefix = 'ssl://'; + $tls = false; // Can't have SSL and TLS at the same time + $secure = 'ssl'; + } elseif ($hostinfo[2] == 'tls') { + $tls = true; + // tls doesn't use a prefix + $secure = 'tls'; + } + //Do we need the OpenSSL extension? + $sslext = defined('OPENSSL_ALGO_SHA1'); + if ('tls' === $secure or 'ssl' === $secure) { + //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled + if (!$sslext) { + throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL); + } + } + $host = $hostinfo[3]; + $port = $this->Port; + $tport = (integer)$hostinfo[4]; + if ($tport > 0 and $tport < 65536) { + $port = $tport; + } + if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) { + try { + if ($this->Helo) { + $hello = $this->Helo; + } else { + $hello = $this->serverHostname(); + } + $this->smtp->hello($hello); + //Automatically enable TLS encryption if: + // * it's not disabled + // * we have openssl extension + // * we are not already using SSL + // * the server offers STARTTLS + if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) { + $tls = true; + } + if ($tls) { + if (!$this->smtp->startTLS()) { + throw new phpmailerException($this->lang('connect_host')); + } + // We must resend HELO after tls negotiation + $this->smtp->hello($hello); + } + if ($this->SMTPAuth) { + if (!$this->smtp->authenticate( + $this->Username, + $this->Password, + $this->AuthType, + $this->Realm, + $this->Workstation + ) + ) { + throw new phpmailerException($this->lang('authenticate')); + } + } + return true; + } catch (phpmailerException $exc) { + $lastexception = $exc; + $this->edebug($exc->getMessage()); + // We must have connected, but then failed TLS or Auth, so close connection nicely + $this->smtp->quit(); + } + } + } + // If we get here, all connection attempts have failed, so close connection hard + $this->smtp->close(); + // As we've caught all exceptions, just report whatever the last one was + if ($this->exceptions and !is_null($lastexception)) { + throw $lastexception; + } + return false; + } + + /** + * Close the active SMTP session if one exists. + * @return void + */ + public function smtpClose() + { + if (is_a($this->smtp, 'SMTP')) { + if ($this->smtp->connected()) { + $this->smtp->quit(); + $this->smtp->close(); + } + } + } + + /** + * Set the language for error messages. + * Returns false if it cannot load the language file. + * The default language is English. + * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr") + * @param string $lang_path Path to the language file directory, with trailing separator (slash) + * @return boolean + * @access public + */ + public function setLanguage($langcode = 'en', $lang_path = '') + { + // Define full set of translatable strings in English + $PHPMAILER_LANG = array( + 'authenticate' => 'SMTP Error: Could not authenticate.', + 'connect_host' => 'SMTP Error: Could not connect to SMTP host.', + 'data_not_accepted' => 'SMTP Error: data not accepted.', + 'empty_message' => 'Message body empty', + 'encoding' => 'Unknown encoding: ', + 'execute' => 'Could not execute: ', + 'file_access' => 'Could not access file: ', + 'file_open' => 'File Error: Could not open file: ', + 'from_failed' => 'The following From address failed: ', + 'instantiate' => 'Could not instantiate mail function.', + 'invalid_address' => 'Invalid address: ', + 'mailer_not_supported' => ' mailer is not supported.', + 'provide_address' => 'You must provide at least one recipient email address.', + 'recipients_failed' => 'SMTP Error: The following recipients failed: ', + 'signing' => 'Signing Error: ', + 'smtp_connect_failed' => 'SMTP connect() failed.', + 'smtp_error' => 'SMTP server error: ', + 'variable_set' => 'Cannot set or reset variable: ', + 'extension_missing' => 'Extension missing: ' + ); + if (empty($lang_path)) { + // Calculate an absolute path so it can work if CWD is not here + $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR; + } + $foundlang = true; + $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php'; + // There is no English translation file + if ($langcode != 'en') { + // Make sure language file path is readable + if (!is_readable($lang_file)) { + $foundlang = false; + } else { + // Overwrite language-specific strings. + // This way we'll never have missing translation keys. + $foundlang = include $lang_file; + } + } + $this->language = $PHPMAILER_LANG; + return (boolean)$foundlang; // Returns false if language not found + } + + /** + * Get the array of strings for the current language. + * @return array + */ + public function getTranslations() + { + return $this->language; + } + + /** + * Create recipient headers. + * @access public + * @param string $type + * @param array $addr An array of recipient, + * where each recipient is a 2-element indexed array with element 0 containing an address + * and element 1 containing a name, like: + * array(array('joe@example.com', 'Joe User'), array('zoe@example.com', 'Zoe User')) + * @return string + */ + public function addrAppend($type, $addr) + { + $addresses = array(); + foreach ($addr as $address) { + $addresses[] = $this->addrFormat($address); + } + return $type . ': ' . implode(', ', $addresses) . $this->LE; + } + + /** + * Format an address for use in a message header. + * @access public + * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name + * like array('joe@example.com', 'Joe User') + * @return string + */ + public function addrFormat($addr) + { + if (empty($addr[1])) { // No name provided + return $this->secureHeader($addr[0]); + } else { + return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader( + $addr[0] + ) . '>'; + } + } + + /** + * Word-wrap message. + * For use with mailers that do not automatically perform wrapping + * and for quoted-printable encoded messages. + * Original written by philippe. + * @param string $message The message to wrap + * @param integer $length The line length to wrap to + * @param boolean $qp_mode Whether to run in Quoted-Printable mode + * @access public + * @return string + */ + public function wrapText($message, $length, $qp_mode = false) + { + if ($qp_mode) { + $soft_break = sprintf(' =%s', $this->LE); + } else { + $soft_break = $this->LE; + } + // If utf-8 encoding is used, we will need to make sure we don't + // split multibyte characters when we wrap + $is_utf8 = (strtolower($this->CharSet) == 'utf-8'); + $lelen = strlen($this->LE); + $crlflen = strlen(self::CRLF); + + $message = $this->fixEOL($message); + //Remove a trailing line break + if (substr($message, -$lelen) == $this->LE) { + $message = substr($message, 0, -$lelen); + } + + //Split message into lines + $lines = explode($this->LE, $message); + //Message will be rebuilt in here + $message = ''; + foreach ($lines as $line) { + $words = explode(' ', $line); + $buf = ''; + $firstword = true; + foreach ($words as $word) { + if ($qp_mode and (strlen($word) > $length)) { + $space_left = $length - strlen($buf) - $crlflen; + if (!$firstword) { + if ($space_left > 20) { + $len = $space_left; + if ($is_utf8) { + $len = $this->utf8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == '=') { + $len--; + } elseif (substr($word, $len - 2, 1) == '=') { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + $buf .= ' ' . $part; + $message .= $buf . sprintf('=%s', self::CRLF); + } else { + $message .= $buf . $soft_break; + } + $buf = ''; + } + while (strlen($word) > 0) { + if ($length <= 0) { + break; + } + $len = $length; + if ($is_utf8) { + $len = $this->utf8CharBoundary($word, $len); + } elseif (substr($word, $len - 1, 1) == '=') { + $len--; + } elseif (substr($word, $len - 2, 1) == '=') { + $len -= 2; + } + $part = substr($word, 0, $len); + $word = substr($word, $len); + + if (strlen($word) > 0) { + $message .= $part . sprintf('=%s', self::CRLF); + } else { + $buf = $part; + } + } + } else { + $buf_o = $buf; + if (!$firstword) { + $buf .= ' '; + } + $buf .= $word; + + if (strlen($buf) > $length and $buf_o != '') { + $message .= $buf_o . $soft_break; + $buf = $word; + } + } + $firstword = false; + } + $message .= $buf . self::CRLF; + } + + return $message; + } + + /** + * Find the last character boundary prior to $maxLength in a utf-8 + * quoted-printable encoded string. + * Original written by Colin Brown. + * @access public + * @param string $encodedText utf-8 QP text + * @param integer $maxLength Find the last character boundary prior to this length + * @return integer + */ + public function utf8CharBoundary($encodedText, $maxLength) + { + $foundSplitPos = false; + $lookBack = 3; + while (!$foundSplitPos) { + $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); + $encodedCharPos = strpos($lastChunk, '='); + if (false !== $encodedCharPos) { + // Found start of encoded character byte within $lookBack block. + // Check the encoded byte value (the 2 chars after the '=') + $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); + $dec = hexdec($hex); + if ($dec < 128) { + // Single byte character. + // If the encoded char was found at pos 0, it will fit + // otherwise reduce maxLength to start of the encoded char + if ($encodedCharPos > 0) { + $maxLength = $maxLength - ($lookBack - $encodedCharPos); + } + $foundSplitPos = true; + } elseif ($dec >= 192) { + // First byte of a multi byte character + // Reduce maxLength to split at start of character + $maxLength = $maxLength - ($lookBack - $encodedCharPos); + $foundSplitPos = true; + } elseif ($dec < 192) { + // Middle byte of a multi byte character, look further back + $lookBack += 3; + } + } else { + // No encoded character found + $foundSplitPos = true; + } + } + return $maxLength; + } + + /** + * Apply word wrapping to the message body. + * Wraps the message body to the number of chars set in the WordWrap property. + * You should only do this to plain-text bodies as wrapping HTML tags may break them. + * This is called automatically by createBody(), so you don't need to call it yourself. + * @access public + * @return void + */ + public function setWordWrap() + { + if ($this->WordWrap < 1) { + return; + } + + switch ($this->message_type) { + case 'alt': + case 'alt_inline': + case 'alt_attach': + case 'alt_inline_attach': + $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap); + break; + default: + $this->Body = $this->wrapText($this->Body, $this->WordWrap); + break; + } + } + + /** + * Assemble message headers. + * @access public + * @return string The assembled headers + */ + public function createHeader() + { + $result = ''; + + if ($this->MessageDate == '') { + $this->MessageDate = self::rfcDate(); + } + $result .= $this->headerLine('Date', $this->MessageDate); + + // To be created automatically by mail() + if ($this->SingleTo) { + if ($this->Mailer != 'mail') { + foreach ($this->to as $toaddr) { + $this->SingleToArray[] = $this->addrFormat($toaddr); + } + } + } else { + if (count($this->to) > 0) { + if ($this->Mailer != 'mail') { + $result .= $this->addrAppend('To', $this->to); + } + } elseif (count($this->cc) == 0) { + $result .= $this->headerLine('To', 'undisclosed-recipients:;'); + } + } + + $result .= $this->addrAppend('From', array(array(trim($this->From), $this->FromName))); + + // sendmail and mail() extract Cc from the header before sending + if (count($this->cc) > 0) { + $result .= $this->addrAppend('Cc', $this->cc); + } + + // sendmail and mail() extract Bcc from the header before sending + if (( + $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail' + ) + and count($this->bcc) > 0 + ) { + $result .= $this->addrAppend('Bcc', $this->bcc); + } + + if (count($this->ReplyTo) > 0) { + $result .= $this->addrAppend('Reply-To', $this->ReplyTo); + } + + // mail() sets the subject itself + if ($this->Mailer != 'mail') { + $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject))); + } + + if ('' != $this->MessageID and preg_match('/^<.*@.*>$/', $this->MessageID)) { + $this->lastMessageID = $this->MessageID; + } else { + $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname()); + } + $result .= $this->headerLine('Message-ID', $this->lastMessageID); + if (!is_null($this->Priority)) { + $result .= $this->headerLine('X-Priority', $this->Priority); + } + if ($this->XMailer == '') { + $result .= $this->headerLine( + 'X-Mailer', + 'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer)' + ); + } else { + $myXmailer = trim($this->XMailer); + if ($myXmailer) { + $result .= $this->headerLine('X-Mailer', $myXmailer); + } + } + + if ($this->ConfirmReadingTo != '') { + $result .= $this->headerLine('Disposition-Notification-To', '<' . $this->ConfirmReadingTo . '>'); + } + + // Add custom headers + foreach ($this->CustomHeader as $header) { + $result .= $this->headerLine( + trim($header[0]), + $this->encodeHeader(trim($header[1])) + ); + } + if (!$this->sign_key_file) { + $result .= $this->headerLine('MIME-Version', '1.0'); + $result .= $this->getMailMIME(); + } + + return $result; + } + + /** + * Get the message MIME type headers. + * @access public + * @return string + */ + public function getMailMIME() + { + $result = ''; + $ismultipart = true; + switch ($this->message_type) { + case 'inline': + $result .= $this->headerLine('Content-Type', 'multipart/related;'); + $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + case 'attach': + case 'inline_attach': + case 'alt_attach': + case 'alt_inline_attach': + $result .= $this->headerLine('Content-Type', 'multipart/mixed;'); + $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + case 'alt': + case 'alt_inline': + $result .= $this->headerLine('Content-Type', 'multipart/alternative;'); + $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"'); + break; + default: + // Catches case 'plain': and case '': + $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet); + $ismultipart = false; + break; + } + // RFC1341 part 5 says 7bit is assumed if not specified + if ($this->Encoding != '7bit') { + // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE + if ($ismultipart) { + if ($this->Encoding == '8bit') { + $result .= $this->headerLine('Content-Transfer-Encoding', '8bit'); + } + // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible + } else { + $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding); + } + } + + if ($this->Mailer != 'mail') { + $result .= $this->LE; + } + + return $result; + } + + /** + * Returns the whole MIME message. + * Includes complete headers and body. + * Only valid post preSend(). + * @see PHPMailer::preSend() + * @access public + * @return string + */ + public function getSentMIMEMessage() + { + return rtrim($this->MIMEHeader . $this->mailHeader, "\n\r") . self::CRLF . self::CRLF . $this->MIMEBody; + } + + /** + * Assemble the message body. + * Returns an empty string on failure. + * @access public + * @throws phpmailerException + * @return string The assembled message body + */ + public function createBody() + { + $body = ''; + //Create unique IDs and preset boundaries + $this->uniqueid = md5(uniqid(time())); + $this->boundary[1] = 'b1_' . $this->uniqueid; + $this->boundary[2] = 'b2_' . $this->uniqueid; + $this->boundary[3] = 'b3_' . $this->uniqueid; + + if ($this->sign_key_file) { + $body .= $this->getMailMIME() . $this->LE; + } + + $this->setWordWrap(); + + $bodyEncoding = $this->Encoding; + $bodyCharSet = $this->CharSet; + //Can we do a 7-bit downgrade? + if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) { + $bodyEncoding = '7bit'; + $bodyCharSet = 'us-ascii'; + } + //If lines are too long, and we're not already using an encoding that will shorten them, + //change to quoted-printable transfer encoding + if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) { + $this->Encoding = 'quoted-printable'; + $bodyEncoding = 'quoted-printable'; + } + + $altBodyEncoding = $this->Encoding; + $altBodyCharSet = $this->CharSet; + //Can we do a 7-bit downgrade? + if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) { + $altBodyEncoding = '7bit'; + $altBodyCharSet = 'us-ascii'; + } + //If lines are too long, and we're not already using an encoding that will shorten them, + //change to quoted-printable transfer encoding + if ('base64' != $altBodyEncoding and self::hasLineLongerThanMax($this->AltBody)) { + $altBodyEncoding = 'quoted-printable'; + } + //Use this as a preamble in all multipart message types + $mimepre = "This is a multi-part message in MIME format." . $this->LE . $this->LE; + switch ($this->message_type) { + case 'inline': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[1]); + break; + case 'attach': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + case 'inline_attach': + $body .= $mimepre; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/related;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[2]); + $body .= $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + case 'alt': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + if (!empty($this->Ical)) { + $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', ''); + $body .= $this->encodeString($this->Ical, $this->Encoding); + $body .= $this->LE . $this->LE; + } + $body .= $this->endBoundary($this->boundary[1]); + break; + case 'alt_inline': + $body .= $mimepre; + $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/related;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[2]); + $body .= $this->LE; + $body .= $this->endBoundary($this->boundary[1]); + break; + case 'alt_attach': + $body .= $mimepre; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->endBoundary($this->boundary[2]); + $body .= $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + case 'alt_inline_attach': + $body .= $mimepre; + $body .= $this->textLine('--' . $this->boundary[1]); + $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding); + $body .= $this->encodeString($this->AltBody, $altBodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->textLine('--' . $this->boundary[2]); + $body .= $this->headerLine('Content-Type', 'multipart/related;'); + $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"'); + $body .= $this->LE; + $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding); + $body .= $this->encodeString($this->Body, $bodyEncoding); + $body .= $this->LE . $this->LE; + $body .= $this->attachAll('inline', $this->boundary[3]); + $body .= $this->LE; + $body .= $this->endBoundary($this->boundary[2]); + $body .= $this->LE; + $body .= $this->attachAll('attachment', $this->boundary[1]); + break; + default: + // catch case 'plain' and case '' + $body .= $this->encodeString($this->Body, $bodyEncoding); + break; + } + + if ($this->isError()) { + $body = ''; + } elseif ($this->sign_key_file) { + try { + if (!defined('PKCS7_TEXT')) { + throw new phpmailerException($this->lang('extension_missing') . 'openssl'); + } + // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1 + $file = tempnam(sys_get_temp_dir(), 'mail'); + if (false === file_put_contents($file, $body)) { + throw new phpmailerException($this->lang('signing') . ' Could not write temp file'); + } + $signed = tempnam(sys_get_temp_dir(), 'signed'); + //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197 + if (empty($this->sign_extracerts_file)) { + $sign = @openssl_pkcs7_sign( + $file, + $signed, + 'file://' . realpath($this->sign_cert_file), + array('file://' . realpath($this->sign_key_file), $this->sign_key_pass), + null + ); + } else { + $sign = @openssl_pkcs7_sign( + $file, + $signed, + 'file://' . realpath($this->sign_cert_file), + array('file://' . realpath($this->sign_key_file), $this->sign_key_pass), + null, + PKCS7_DETACHED, + $this->sign_extracerts_file + ); + } + if ($sign) { + @unlink($file); + $body = file_get_contents($signed); + @unlink($signed); + //The message returned by openssl contains both headers and body, so need to split them up + $parts = explode("\n\n", $body, 2); + $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE; + $body = $parts[1]; + } else { + @unlink($file); + @unlink($signed); + throw new phpmailerException($this->lang('signing') . openssl_error_string()); + } + } catch (phpmailerException $exc) { + $body = ''; + if ($this->exceptions) { + throw $exc; + } + } + } + return $body; + } + + /** + * Return the start of a message boundary. + * @access protected + * @param string $boundary + * @param string $charSet + * @param string $contentType + * @param string $encoding + * @return string + */ + protected function getBoundary($boundary, $charSet, $contentType, $encoding) + { + $result = ''; + if ($charSet == '') { + $charSet = $this->CharSet; + } + if ($contentType == '') { + $contentType = $this->ContentType; + } + if ($encoding == '') { + $encoding = $this->Encoding; + } + $result .= $this->textLine('--' . $boundary); + $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet); + $result .= $this->LE; + // RFC1341 part 5 says 7bit is assumed if not specified + if ($encoding != '7bit') { + $result .= $this->headerLine('Content-Transfer-Encoding', $encoding); + } + $result .= $this->LE; + + return $result; + } + + /** + * Return the end of a message boundary. + * @access protected + * @param string $boundary + * @return string + */ + protected function endBoundary($boundary) + { + return $this->LE . '--' . $boundary . '--' . $this->LE; + } + + /** + * Set the message type. + * PHPMailer only supports some preset message types, + * not arbitrary MIME structures. + * @access protected + * @return void + */ + protected function setMessageType() + { + $type = array(); + if ($this->alternativeExists()) { + $type[] = 'alt'; + } + if ($this->inlineImageExists()) { + $type[] = 'inline'; + } + if ($this->attachmentExists()) { + $type[] = 'attach'; + } + $this->message_type = implode('_', $type); + if ($this->message_type == '') { + $this->message_type = 'plain'; + } + } + + /** + * Format a header line. + * @access public + * @param string $name + * @param string $value + * @return string + */ + public function headerLine($name, $value) + { + return $name . ': ' . $value . $this->LE; + } + + /** + * Return a formatted mail line. + * @access public + * @param string $value + * @return string + */ + public function textLine($value) + { + return $value . $this->LE; + } + + /** + * Add an attachment from a path on the filesystem. + * Returns false if the file could not be found or read. + * @param string $path Path to the attachment. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @param string $disposition Disposition to use + * @throws phpmailerException + * @return boolean + */ + public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') + { + try { + if (!@is_file($path)) { + throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE); + } + + // If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($path); + } + + $filename = basename($path); + if ($name == '') { + $name = $filename; + } + + $this->attachment[] = array( + 0 => $path, + 1 => $filename, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => false, // isStringAttachment + 6 => $disposition, + 7 => 0 + ); + + } catch (phpmailerException $exc) { + $this->setError($exc->getMessage()); + $this->edebug($exc->getMessage()); + if ($this->exceptions) { + throw $exc; + } + return false; + } + return true; + } + + /** + * Return the array of attachments. + * @return array + */ + public function getAttachments() + { + return $this->attachment; + } + + /** + * Attach all file, string, and binary attachments to the message. + * Returns an empty string on failure. + * @access protected + * @param string $disposition_type + * @param string $boundary + * @return string + */ + protected function attachAll($disposition_type, $boundary) + { + // Return text of body + $mime = array(); + $cidUniq = array(); + $incl = array(); + + // Add all attachments + foreach ($this->attachment as $attachment) { + // Check if it is a valid disposition_filter + if ($attachment[6] == $disposition_type) { + // Check for string attachment + $string = ''; + $path = ''; + $bString = $attachment[5]; + if ($bString) { + $string = $attachment[0]; + } else { + $path = $attachment[0]; + } + + $inclhash = md5(serialize($attachment)); + if (in_array($inclhash, $incl)) { + continue; + } + $incl[] = $inclhash; + $name = $attachment[2]; + $encoding = $attachment[3]; + $type = $attachment[4]; + $disposition = $attachment[6]; + $cid = $attachment[7]; + if ($disposition == 'inline' && array_key_exists($cid, $cidUniq)) { + continue; + } + $cidUniq[$cid] = true; + + $mime[] = sprintf('--%s%s', $boundary, $this->LE); + //Only include a filename property if we have one + if (!empty($name)) { + $mime[] = sprintf( + 'Content-Type: %s; name="%s"%s', + $type, + $this->encodeHeader($this->secureHeader($name)), + $this->LE + ); + } else { + $mime[] = sprintf( + 'Content-Type: %s%s', + $type, + $this->LE + ); + } + // RFC1341 part 5 says 7bit is assumed if not specified + if ($encoding != '7bit') { + $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE); + } + + if ($disposition == 'inline') { + $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE); + } + + // If a filename contains any of these chars, it should be quoted, + // but not otherwise: RFC2183 & RFC2045 5.1 + // Fixes a warning in IETF's msglint MIME checker + // Allow for bypassing the Content-Disposition header totally + if (!(empty($disposition))) { + $encoded_name = $this->encodeHeader($this->secureHeader($name)); + if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) { + $mime[] = sprintf( + 'Content-Disposition: %s; filename="%s"%s', + $disposition, + $encoded_name, + $this->LE . $this->LE + ); + } else { + if (!empty($encoded_name)) { + $mime[] = sprintf( + 'Content-Disposition: %s; filename=%s%s', + $disposition, + $encoded_name, + $this->LE . $this->LE + ); + } else { + $mime[] = sprintf( + 'Content-Disposition: %s%s', + $disposition, + $this->LE . $this->LE + ); + } + } + } else { + $mime[] = $this->LE; + } + + // Encode as string attachment + if ($bString) { + $mime[] = $this->encodeString($string, $encoding); + if ($this->isError()) { + return ''; + } + $mime[] = $this->LE . $this->LE; + } else { + $mime[] = $this->encodeFile($path, $encoding); + if ($this->isError()) { + return ''; + } + $mime[] = $this->LE . $this->LE; + } + } + } + + $mime[] = sprintf('--%s--%s', $boundary, $this->LE); + + return implode('', $mime); + } + + /** + * Encode a file attachment in requested format. + * Returns an empty string on failure. + * @param string $path The full path to the file + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * @throws phpmailerException + * @access protected + * @return string + */ + protected function encodeFile($path, $encoding = 'base64') + { + try { + if (!is_readable($path)) { + throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE); + } + $magic_quotes = get_magic_quotes_runtime(); + if ($magic_quotes) { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + set_magic_quotes_runtime(false); + } else { + //Doesn't exist in PHP 5.4, but we don't need to check because + //get_magic_quotes_runtime always returns false in 5.4+ + //so it will never get here + ini_set('magic_quotes_runtime', false); + } + } + $file_buffer = file_get_contents($path); + $file_buffer = $this->encodeString($file_buffer, $encoding); + if ($magic_quotes) { + if (version_compare(PHP_VERSION, '5.3.0', '<')) { + set_magic_quotes_runtime($magic_quotes); + } else { + ini_set('magic_quotes_runtime', $magic_quotes); + } + } + return $file_buffer; + } catch (Exception $exc) { + $this->setError($exc->getMessage()); + return ''; + } + } + + /** + * Encode a string in requested format. + * Returns an empty string on failure. + * @param string $str The text to encode + * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' + * @access public + * @return string + */ + public function encodeString($str, $encoding = 'base64') + { + $encoded = ''; + switch (strtolower($encoding)) { + case 'base64': + $encoded = chunk_split(base64_encode($str), 76, $this->LE); + break; + case '7bit': + case '8bit': + $encoded = $this->fixEOL($str); + // Make sure it ends with a line break + if (substr($encoded, -(strlen($this->LE))) != $this->LE) { + $encoded .= $this->LE; + } + break; + case 'binary': + $encoded = $str; + break; + case 'quoted-printable': + $encoded = $this->encodeQP($str); + break; + default: + $this->setError($this->lang('encoding') . $encoding); + break; + } + return $encoded; + } + + /** + * Encode a header string optimally. + * Picks shortest of Q, B, quoted-printable or none. + * @access public + * @param string $str + * @param string $position + * @return string + */ + public function encodeHeader($str, $position = 'text') + { + $matchcount = 0; + switch (strtolower($position)) { + case 'phrase': + if (!preg_match('/[\200-\377]/', $str)) { + // Can't use addslashes as we don't know the value of magic_quotes_sybase + $encoded = addcslashes($str, "\0..\37\177\\\""); + if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { + return ($encoded); + } else { + return ("\"$encoded\""); + } + } + $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); + break; + /** @noinspection PhpMissingBreakStatementInspection */ + case 'comment': + $matchcount = preg_match_all('/[()"]/', $str, $matches); + // Intentional fall-through + case 'text': + default: + $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); + break; + } + + //There are no chars that need encoding + if ($matchcount == 0) { + return ($str); + } + + $maxlen = 75 - 7 - strlen($this->CharSet); + // Try to select the encoding which should produce the shortest output + if ($matchcount > strlen($str) / 3) { + // More than a third of the content will need encoding, so B encoding will be most efficient + $encoding = 'B'; + if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) { + // Use a custom function which correctly encodes and wraps long + // multibyte strings without breaking lines within a character + $encoded = $this->base64EncodeWrapMB($str, "\n"); + } else { + $encoded = base64_encode($str); + $maxlen -= $maxlen % 4; + $encoded = trim(chunk_split($encoded, $maxlen, "\n")); + } + } else { + $encoding = 'Q'; + $encoded = $this->encodeQ($str, $position); + $encoded = $this->wrapText($encoded, $maxlen, true); + $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded)); + } + + $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded); + $encoded = trim(str_replace("\n", $this->LE, $encoded)); + + return $encoded; + } + + /** + * Check if a string contains multi-byte characters. + * @access public + * @param string $str multi-byte text to wrap encode + * @return boolean + */ + public function hasMultiBytes($str) + { + if (function_exists('mb_strlen')) { + return (strlen($str) > mb_strlen($str, $this->CharSet)); + } else { // Assume no multibytes (we can't handle without mbstring functions anyway) + return false; + } + } + + /** + * Does a string contain any 8-bit chars (in any charset)? + * @param string $text + * @return boolean + */ + public function has8bitChars($text) + { + return (boolean)preg_match('/[\x80-\xFF]/', $text); + } + + /** + * Encode and wrap long multibyte strings for mail headers + * without breaking lines within a character. + * Adapted from a function by paravoid + * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283 + * @access public + * @param string $str multi-byte text to wrap encode + * @param string $linebreak string to use as linefeed/end-of-line + * @return string + */ + public function base64EncodeWrapMB($str, $linebreak = null) + { + $start = '=?' . $this->CharSet . '?B?'; + $end = '?='; + $encoded = ''; + if ($linebreak === null) { + $linebreak = $this->LE; + } + + $mb_length = mb_strlen($str, $this->CharSet); + // Each line must have length <= 75, including $start and $end + $length = 75 - strlen($start) - strlen($end); + // Average multi-byte ratio + $ratio = $mb_length / strlen($str); + // Base64 has a 4:3 ratio + $avgLength = floor($length * $ratio * .75); + + for ($i = 0; $i < $mb_length; $i += $offset) { + $lookBack = 0; + do { + $offset = $avgLength - $lookBack; + $chunk = mb_substr($str, $i, $offset, $this->CharSet); + $chunk = base64_encode($chunk); + $lookBack++; + } while (strlen($chunk) > $length); + $encoded .= $chunk . $linebreak; + } + + // Chomp the last linefeed + $encoded = substr($encoded, 0, -strlen($linebreak)); + return $encoded; + } + + /** + * Encode a string in quoted-printable format. + * According to RFC2045 section 6.7. + * @access public + * @param string $string The text to encode + * @param integer $line_max Number of chars allowed on a line before wrapping + * @return string + * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 Adapted from this comment + */ + public function encodeQP($string, $line_max = 76) + { + // Use native function if it's available (>= PHP5.3) + if (function_exists('quoted_printable_encode')) { + return quoted_printable_encode($string); + } + // Fall back to a pure PHP implementation + $string = str_replace( + array('%20', '%0D%0A.', '%0D%0A', '%'), + array(' ', "\r\n=2E", "\r\n", '='), + rawurlencode($string) + ); + return preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string); + } + + /** + * Backward compatibility wrapper for an old QP encoding function that was removed. + * @see PHPMailer::encodeQP() + * @access public + * @param string $string + * @param integer $line_max + * @param boolean $space_conv + * @return string + * @deprecated Use encodeQP instead. + */ + public function encodeQPphp( + $string, + $line_max = 76, + /** @noinspection PhpUnusedParameterInspection */ $space_conv = false + ) { + return $this->encodeQP($string, $line_max); + } + + /** + * Encode a string using Q encoding. + * @link http://tools.ietf.org/html/rfc2047 + * @param string $str the text to encode + * @param string $position Where the text is going to be used, see the RFC for what that means + * @access public + * @return string + */ + public function encodeQ($str, $position = 'text') + { + // There should not be any EOL in the string + $pattern = ''; + $encoded = str_replace(array("\r", "\n"), '', $str); + switch (strtolower($position)) { + case 'phrase': + // RFC 2047 section 5.3 + $pattern = '^A-Za-z0-9!*+\/ -'; + break; + /** @noinspection PhpMissingBreakStatementInspection */ + case 'comment': + // RFC 2047 section 5.2 + $pattern = '\(\)"'; + // intentional fall-through + // for this reason we build the $pattern without including delimiters and [] + case 'text': + default: + // RFC 2047 section 5.1 + // Replace every high ascii, control, =, ? and _ characters + $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern; + break; + } + $matches = array(); + if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) { + // If the string contains an '=', make sure it's the first thing we replace + // so as to avoid double-encoding + $eqkey = array_search('=', $matches[0]); + if (false !== $eqkey) { + unset($matches[0][$eqkey]); + array_unshift($matches[0], '='); + } + foreach (array_unique($matches[0]) as $char) { + $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded); + } + } + // Replace every spaces to _ (more readable than =20) + return str_replace(' ', '_', $encoded); + } + + /** + * Add a string or binary attachment (non-filesystem). + * This method can be used to attach ascii or binary data, + * such as a BLOB record from a database. + * @param string $string String attachment data. + * @param string $filename Name of the attachment. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @param string $disposition Disposition to use + * @return void + */ + public function addStringAttachment( + $string, + $filename, + $encoding = 'base64', + $type = '', + $disposition = 'attachment' + ) { + // If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($filename); + } + // Append to $attachment array + $this->attachment[] = array( + 0 => $string, + 1 => $filename, + 2 => basename($filename), + 3 => $encoding, + 4 => $type, + 5 => true, // isStringAttachment + 6 => $disposition, + 7 => 0 + ); + } + + /** + * Add an embedded (inline) attachment from a file. + * This can include images, sounds, and just about any other document type. + * These differ from 'regular' attachments in that they are intended to be + * displayed inline with the message, not just attached for download. + * This is used in HTML messages that embed the images + * the HTML refers to using the $cid value. + * @param string $path Path to the attachment. + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML. + * @param string $name Overrides the attachment name. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File MIME type. + * @param string $disposition Disposition to use + * @return boolean True on successfully adding an attachment + */ + public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') + { + if (!@is_file($path)) { + $this->setError($this->lang('file_access') . $path); + return false; + } + + // If a MIME type is not specified, try to work it out from the file name + if ($type == '') { + $type = self::filenameToType($path); + } + + $filename = basename($path); + if ($name == '') { + $name = $filename; + } + + // Append to $attachment array + $this->attachment[] = array( + 0 => $path, + 1 => $filename, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => false, // isStringAttachment + 6 => $disposition, + 7 => $cid + ); + return true; + } + + /** + * Add an embedded stringified attachment. + * This can include images, sounds, and just about any other document type. + * Be sure to set the $type to an image type for images: + * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'. + * @param string $string The attachment binary data. + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML. + * @param string $name + * @param string $encoding File encoding (see $Encoding). + * @param string $type MIME type. + * @param string $disposition Disposition to use + * @return boolean True on successfully adding an attachment + */ + public function addStringEmbeddedImage( + $string, + $cid, + $name = '', + $encoding = 'base64', + $type = '', + $disposition = 'inline' + ) { + // If a MIME type is not specified, try to work it out from the name + if ($type == '' and !empty($name)) { + $type = self::filenameToType($name); + } + + // Append to $attachment array + $this->attachment[] = array( + 0 => $string, + 1 => $name, + 2 => $name, + 3 => $encoding, + 4 => $type, + 5 => true, // isStringAttachment + 6 => $disposition, + 7 => $cid + ); + return true; + } + + /** + * Check if an inline attachment is present. + * @access public + * @return boolean + */ + public function inlineImageExists() + { + foreach ($this->attachment as $attachment) { + if ($attachment[6] == 'inline') { + return true; + } + } + return false; + } + + /** + * Check if an attachment (non-inline) is present. + * @return boolean + */ + public function attachmentExists() + { + foreach ($this->attachment as $attachment) { + if ($attachment[6] == 'attachment') { + return true; + } + } + return false; + } + + /** + * Check if this message has an alternative body set. + * @return boolean + */ + public function alternativeExists() + { + return !empty($this->AltBody); + } + + /** + * Clear queued addresses of given kind. + * @access protected + * @param string $kind 'to', 'cc', or 'bcc' + * @return void + */ + public function clearQueuedAddresses($kind) + { + $RecipientsQueue = $this->RecipientsQueue; + foreach ($RecipientsQueue as $address => $params) { + if ($params[0] == $kind) { + unset($this->RecipientsQueue[$address]); + } + } + } + + /** + * Clear all To recipients. + * @return void + */ + public function clearAddresses() + { + foreach ($this->to as $to) { + unset($this->all_recipients[strtolower($to[0])]); + } + $this->to = array(); + $this->clearQueuedAddresses('to'); + } + + /** + * Clear all CC recipients. + * @return void + */ + public function clearCCs() + { + foreach ($this->cc as $cc) { + unset($this->all_recipients[strtolower($cc[0])]); + } + $this->cc = array(); + $this->clearQueuedAddresses('cc'); + } + + /** + * Clear all BCC recipients. + * @return void + */ + public function clearBCCs() + { + foreach ($this->bcc as $bcc) { + unset($this->all_recipients[strtolower($bcc[0])]); + } + $this->bcc = array(); + $this->clearQueuedAddresses('bcc'); + } + + /** + * Clear all ReplyTo recipients. + * @return void + */ + public function clearReplyTos() + { + $this->ReplyTo = array(); + $this->ReplyToQueue = array(); + } + + /** + * Clear all recipient types. + * @return void + */ + public function clearAllRecipients() + { + $this->to = array(); + $this->cc = array(); + $this->bcc = array(); + $this->all_recipients = array(); + $this->RecipientsQueue = array(); + } + + /** + * Clear all filesystem, string, and binary attachments. + * @return void + */ + public function clearAttachments() + { + $this->attachment = array(); + } + + /** + * Clear all custom headers. + * @return void + */ + public function clearCustomHeaders() + { + $this->CustomHeader = array(); + } + + /** + * Add an error message to the error container. + * @access protected + * @param string $msg + * @return void + */ + protected function setError($msg) + { + $this->error_count++; + if ($this->Mailer == 'smtp' and !is_null($this->smtp)) { + $lasterror = $this->smtp->getError(); + if (!empty($lasterror['error'])) { + $msg .= $this->lang('smtp_error') . $lasterror['error']; + if (!empty($lasterror['detail'])) { + $msg .= ' Detail: '. $lasterror['detail']; + } + if (!empty($lasterror['smtp_code'])) { + $msg .= ' SMTP code: ' . $lasterror['smtp_code']; + } + if (!empty($lasterror['smtp_code_ex'])) { + $msg .= ' Additional SMTP info: ' . $lasterror['smtp_code_ex']; + } + } + } + $this->ErrorInfo = $msg; + } + + /** + * Return an RFC 822 formatted date. + * @access public + * @return string + * @static + */ + public static function rfcDate() + { + // Set the time zone to whatever the default is to avoid 500 errors + // Will default to UTC if it's not set properly in php.ini + date_default_timezone_set(@date_default_timezone_get()); + return date('D, j M Y H:i:s O'); + } + + /** + * Get the server hostname. + * Returns 'localhost.localdomain' if unknown. + * @access protected + * @return string + */ + protected function serverHostname() + { + $result = 'localhost.localdomain'; + if (!empty($this->Hostname)) { + $result = $this->Hostname; + } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { + $result = $_SERVER['SERVER_NAME']; + } elseif (function_exists('gethostname') && gethostname() !== false) { + $result = gethostname(); + } elseif (php_uname('n') !== false) { + $result = php_uname('n'); + } + return $result; + } + + /** + * Get an error message in the current language. + * @access protected + * @param string $key + * @return string + */ + protected function lang($key) + { + if (count($this->language) < 1) { + $this->setLanguage('en'); // set the default language + } + + if (array_key_exists($key, $this->language)) { + if ($key == 'smtp_connect_failed') { + //Include a link to troubleshooting docs on SMTP connection failure + //this is by far the biggest cause of support questions + //but it's usually not PHPMailer's fault. + return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting'; + } + return $this->language[$key]; + } else { + //Return the key as a fallback + return $key; + } + } + + /** + * Check if an error occurred. + * @access public + * @return boolean True if an error did occur. + */ + public function isError() + { + return ($this->error_count > 0); + } + + /** + * Ensure consistent line endings in a string. + * Changes every end of line from CRLF, CR or LF to $this->LE. + * @access public + * @param string $str String to fixEOL + * @return string + */ + public function fixEOL($str) + { + // Normalise to \n + $nstr = str_replace(array("\r\n", "\r"), "\n", $str); + // Now convert LE as needed + if ($this->LE !== "\n") { + $nstr = str_replace("\n", $this->LE, $nstr); + } + return $nstr; + } + + /** + * Add a custom header. + * $name value can be overloaded to contain + * both header name and value (name:value) + * @access public + * @param string $name Custom header name + * @param string $value Header value + * @return void + */ + public function addCustomHeader($name, $value = null) + { + if ($value === null) { + // Value passed in as name:value + $this->CustomHeader[] = explode(':', $name, 2); + } else { + $this->CustomHeader[] = array($name, $value); + } + } + + /** + * Returns all custom headers. + * @return array + */ + public function getCustomHeaders() + { + return $this->CustomHeader; + } + + /** + * Create a message from an HTML string. + * Automatically makes modifications for inline images and backgrounds + * and creates a plain-text version by converting the HTML. + * Overwrites any existing values in $this->Body and $this->AltBody + * @access public + * @param string $message HTML message string + * @param string $basedir baseline directory for path + * @param boolean|callable $advanced Whether to use the internal HTML to text converter + * or your own custom converter @see PHPMailer::html2text() + * @return string $message + */ + public function msgHTML($message, $basedir = '', $advanced = false) + { + preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images); + if (array_key_exists(2, $images)) { + foreach ($images[2] as $imgindex => $url) { + // Convert data URIs into embedded images + if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) { + $data = substr($url, strpos($url, ',')); + if ($match[2]) { + $data = base64_decode($data); + } else { + $data = rawurldecode($data); + } + $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 + if ($this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1])) { + $message = str_replace( + $images[0][$imgindex], + $images[1][$imgindex] . '="cid:' . $cid . '"', + $message + ); + } + } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[a-z][a-z0-9+.-]*://#i', $url)) { + // Do not change urls for absolute images (thanks to corvuscorax) + // Do not change urls that are already inline images + $filename = basename($url); + $directory = dirname($url); + if ($directory == '.') { + $directory = ''; + } + $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 + if (strlen($basedir) > 1 && substr($basedir, -1) != '/') { + $basedir .= '/'; + } + if (strlen($directory) > 1 && substr($directory, -1) != '/') { + $directory .= '/'; + } + if ($this->addEmbeddedImage( + $basedir . $directory . $filename, + $cid, + $filename, + 'base64', + self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION)) + ) + ) { + $message = preg_replace( + '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui', + $images[1][$imgindex] . '="cid:' . $cid . '"', + $message + ); + } + } + } + } + $this->isHTML(true); + // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better + $this->Body = $this->normalizeBreaks($message); + $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); + if (!$this->alternativeExists()) { + $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . + self::CRLF . self::CRLF; + } + return $this->Body; + } + + /** + * Convert an HTML string into plain text. + * This is used by msgHTML(). + * Note - older versions of this function used a bundled advanced converter + * which was been removed for license reasons in #232 + * Example usage: + * + * // Use default conversion + * $plain = $mail->html2text($html); + * // Use your own custom converter + * $plain = $mail->html2text($html, function($html) { + * $converter = new MyHtml2text($html); + * return $converter->get_text(); + * }); + * + * @param string $html The HTML text to convert + * @param boolean|callable $advanced Any boolean value to use the internal converter, + * or provide your own callable for custom conversion. + * @return string + */ + public function html2text($html, $advanced = false) + { + if (is_callable($advanced)) { + return call_user_func($advanced, $html); + } + return html_entity_decode( + trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), + ENT_QUOTES, + $this->CharSet + ); + } + + /** + * Get the MIME type for a file extension. + * @param string $ext File extension + * @access public + * @return string MIME type of file. + * @static + */ + public static function _mime_types($ext = '') + { + $mimes = array( + 'xl' => 'application/excel', + 'js' => 'application/javascript', + 'hqx' => 'application/mac-binhex40', + 'cpt' => 'application/mac-compactpro', + 'bin' => 'application/macbinary', + 'doc' => 'application/msword', + 'word' => 'application/msword', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'class' => 'application/octet-stream', + 'dll' => 'application/octet-stream', + 'dms' => 'application/octet-stream', + 'exe' => 'application/octet-stream', + 'lha' => 'application/octet-stream', + 'lzh' => 'application/octet-stream', + 'psd' => 'application/octet-stream', + 'sea' => 'application/octet-stream', + 'so' => 'application/octet-stream', + 'oda' => 'application/oda', + 'pdf' => 'application/pdf', + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'mif' => 'application/vnd.mif', + 'xls' => 'application/vnd.ms-excel', + 'ppt' => 'application/vnd.ms-powerpoint', + 'wbxml' => 'application/vnd.wap.wbxml', + 'wmlc' => 'application/vnd.wap.wmlc', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'gtar' => 'application/x-gtar', + 'php3' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'php' => 'application/x-httpd-php', + 'phtml' => 'application/x-httpd-php', + 'phps' => 'application/x-httpd-php-source', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'tar' => 'application/x-tar', + 'tgz' => 'application/x-tar', + 'xht' => 'application/xhtml+xml', + 'xhtml' => 'application/xhtml+xml', + 'zip' => 'application/zip', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mp2' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mpga' => 'audio/mpeg', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'ram' => 'audio/x-pn-realaudio', + 'rm' => 'audio/x-pn-realaudio', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'ra' => 'audio/x-realaudio', + 'wav' => 'audio/x-wav', + 'bmp' => 'image/bmp', + 'gif' => 'image/gif', + 'jpeg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'png' => 'image/png', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'eml' => 'message/rfc822', + 'css' => 'text/css', + 'html' => 'text/html', + 'htm' => 'text/html', + 'shtml' => 'text/html', + 'log' => 'text/plain', + 'text' => 'text/plain', + 'txt' => 'text/plain', + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'vcf' => 'text/vcard', + 'vcard' => 'text/vcard', + 'xml' => 'text/xml', + 'xsl' => 'text/xml', + 'mpeg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mov' => 'video/quicktime', + 'qt' => 'video/quicktime', + 'rv' => 'video/vnd.rn-realvideo', + 'avi' => 'video/x-msvideo', + 'movie' => 'video/x-sgi-movie' + ); + if (array_key_exists(strtolower($ext), $mimes)) { + return $mimes[strtolower($ext)]; + } + return 'application/octet-stream'; + } + + /** + * Map a file name to a MIME type. + * Defaults to 'application/octet-stream', i.e.. arbitrary binary data. + * @param string $filename A file name or full path, does not need to exist as a file + * @return string + * @static + */ + public static function filenameToType($filename) + { + // In case the path is a URL, strip any query string before getting extension + $qpos = strpos($filename, '?'); + if (false !== $qpos) { + $filename = substr($filename, 0, $qpos); + } + $pathinfo = self::mb_pathinfo($filename); + return self::_mime_types($pathinfo['extension']); + } + + /** + * Multi-byte-safe pathinfo replacement. + * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe. + * Works similarly to the one in PHP >= 5.2.0 + * @link http://www.php.net/manual/en/function.pathinfo.php#107461 + * @param string $path A filename or path, does not need to exist as a file + * @param integer|string $options Either a PATHINFO_* constant, + * or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2 + * @return string|array + * @static + */ + public static function mb_pathinfo($path, $options = null) + { + $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''); + $pathinfo = array(); + if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) { + if (array_key_exists(1, $pathinfo)) { + $ret['dirname'] = $pathinfo[1]; + } + if (array_key_exists(2, $pathinfo)) { + $ret['basename'] = $pathinfo[2]; + } + if (array_key_exists(5, $pathinfo)) { + $ret['extension'] = $pathinfo[5]; + } + if (array_key_exists(3, $pathinfo)) { + $ret['filename'] = $pathinfo[3]; + } + } + switch ($options) { + case PATHINFO_DIRNAME: + case 'dirname': + return $ret['dirname']; + case PATHINFO_BASENAME: + case 'basename': + return $ret['basename']; + case PATHINFO_EXTENSION: + case 'extension': + return $ret['extension']; + case PATHINFO_FILENAME: + case 'filename': + return $ret['filename']; + default: + return $ret; + } + } + + /** + * Set or reset instance properties. + * You should avoid this function - it's more verbose, less efficient, more error-prone and + * harder to debug than setting properties directly. + * Usage Example: + * `$mail->set('SMTPSecure', 'tls');` + * is the same as: + * `$mail->SMTPSecure = 'tls';` + * @access public + * @param string $name The property name to set + * @param mixed $value The value to set the property to + * @return boolean + * @TODO Should this not be using the __set() magic function? + */ + public function set($name, $value = '') + { + if (property_exists($this, $name)) { + $this->$name = $value; + return true; + } else { + $this->setError($this->lang('variable_set') . $name); + return false; + } + } + + /** + * Strip newlines to prevent header injection. + * @access public + * @param string $str + * @return string + */ + public function secureHeader($str) + { + return trim(str_replace(array("\r", "\n"), '', $str)); + } + + /** + * Normalize line breaks in a string. + * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format. + * Defaults to CRLF (for message bodies) and preserves consecutive breaks. + * @param string $text + * @param string $breaktype What kind of line break to use, defaults to CRLF + * @return string + * @access public + * @static + */ + public static function normalizeBreaks($text, $breaktype = "\r\n") + { + return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text); + } + + /** + * Set the public and private key files and password for S/MIME signing. + * @access public + * @param string $cert_filename + * @param string $key_filename + * @param string $key_pass Password for private key + * @param string $extracerts_filename Optional path to chain certificate + */ + public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '') + { + $this->sign_cert_file = $cert_filename; + $this->sign_key_file = $key_filename; + $this->sign_key_pass = $key_pass; + $this->sign_extracerts_file = $extracerts_filename; + } + + /** + * Quoted-Printable-encode a DKIM header. + * @access public + * @param string $txt + * @return string + */ + public function DKIM_QP($txt) + { + $line = ''; + for ($i = 0; $i < strlen($txt); $i++) { + $ord = ord($txt[$i]); + if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) { + $line .= $txt[$i]; + } else { + $line .= '=' . sprintf('%02X', $ord); + } + } + return $line; + } + + /** + * Generate a DKIM signature. + * @access public + * @param string $signHeader + * @throws phpmailerException + * @return string + */ + public function DKIM_Sign($signHeader) + { + if (!defined('PKCS7_TEXT')) { + if ($this->exceptions) { + throw new phpmailerException($this->lang('extension_missing') . 'openssl'); + } + return ''; + } + $privKeyStr = file_get_contents($this->DKIM_private); + if ($this->DKIM_passphrase != '') { + $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); + } else { + $privKey = openssl_pkey_get_private($privKeyStr); + } + if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) { //sha1WithRSAEncryption + openssl_pkey_free($privKey); + return base64_encode($signature); + } + openssl_pkey_free($privKey); + return ''; + } + + /** + * Generate a DKIM canonicalization header. + * @access public + * @param string $signHeader Header + * @return string + */ + public function DKIM_HeaderC($signHeader) + { + $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader); + $lines = explode("\r\n", $signHeader); + foreach ($lines as $key => $line) { + list($heading, $value) = explode(':', $line, 2); + $heading = strtolower($heading); + $value = preg_replace('/\s{2,}/', ' ', $value); // Compress useless spaces + $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value + } + $signHeader = implode("\r\n", $lines); + return $signHeader; + } + + /** + * Generate a DKIM canonicalization body. + * @access public + * @param string $body Message Body + * @return string + */ + public function DKIM_BodyC($body) + { + if ($body == '') { + return "\r\n"; + } + // stabilize line endings + $body = str_replace("\r\n", "\n", $body); + $body = str_replace("\n", "\r\n", $body); + // END stabilize line endings + while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") { + $body = substr($body, 0, strlen($body) - 2); + } + return $body; + } + + /** + * Create the DKIM header and body in a new message header. + * @access public + * @param string $headers_line Header lines + * @param string $subject Subject + * @param string $body Body + * @return string + */ + public function DKIM_Add($headers_line, $subject, $body) + { + $DKIMsignatureType = 'rsa-sha256'; // Signature & hash algorithms + $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body + $DKIMquery = 'dns/txt'; // Query method + $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) + $subject_header = "Subject: $subject"; + $headers = explode($this->LE, $headers_line); + $from_header = ''; + $to_header = ''; + $date_header = ''; + $current = ''; + foreach ($headers as $header) { + if (strpos($header, 'From:') === 0) { + $from_header = $header; + $current = 'from_header'; + } elseif (strpos($header, 'To:') === 0) { + $to_header = $header; + $current = 'to_header'; + } elseif (strpos($header, 'Date:') === 0) { + $date_header = $header; + $current = 'date_header'; + } else { + if (!empty($$current) && strpos($header, ' =?') === 0) { + $$current .= $header; + } else { + $current = ''; + } + } + } + $from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); + $to = str_replace('|', '=7C', $this->DKIM_QP($to_header)); + $date = str_replace('|', '=7C', $this->DKIM_QP($date_header)); + $subject = str_replace( + '|', + '=7C', + $this->DKIM_QP($subject_header) + ); // Copied header fields (dkim-quoted-printable) + $body = $this->DKIM_BodyC($body); + $DKIMlen = strlen($body); // Length of body + $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body + if ('' == $this->DKIM_identity) { + $ident = ''; + } else { + $ident = ' i=' . $this->DKIM_identity . ';'; + } + $dkimhdrs = 'DKIM-Signature: v=1; a=' . + $DKIMsignatureType . '; q=' . + $DKIMquery . '; l=' . + $DKIMlen . '; s=' . + $this->DKIM_selector . + ";\r\n" . + "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . + "\th=From:To:Date:Subject;\r\n" . + "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . + "\tz=$from\r\n" . + "\t|$to\r\n" . + "\t|$date\r\n" . + "\t|$subject;\r\n" . + "\tbh=" . $DKIMb64 . ";\r\n" . + "\tb="; + $toSign = $this->DKIM_HeaderC( + $from_header . "\r\n" . + $to_header . "\r\n" . + $date_header . "\r\n" . + $subject_header . "\r\n" . + $dkimhdrs + ); + $signed = $this->DKIM_Sign($toSign); + return $dkimhdrs . $signed . "\r\n"; + } + + /** + * Detect if a string contains a line longer than the maximum line length allowed. + * @param string $str + * @return boolean + * @static + */ + public static function hasLineLongerThanMax($str) + { + //+2 to include CRLF line break for a 1000 total + return (boolean)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + 2).',})/m', $str); + } + + /** + * Allows for public read access to 'to' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getToAddresses() + { + return $this->to; + } + + /** + * Allows for public read access to 'cc' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getCcAddresses() + { + return $this->cc; + } + + /** + * Allows for public read access to 'bcc' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getBccAddresses() + { + return $this->bcc; + } + + /** + * Allows for public read access to 'ReplyTo' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getReplyToAddresses() + { + return $this->ReplyTo; + } + + /** + * Allows for public read access to 'all_recipients' property. + * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. + * @access public + * @return array + */ + public function getAllRecipientAddresses() + { + return $this->all_recipients; + } + + /** + * Perform a callback. + * @param boolean $isSent + * @param array $to + * @param array $cc + * @param array $bcc + * @param string $subject + * @param string $body + * @param string $from + */ + protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from) + { + if (!empty($this->action_function) && is_callable($this->action_function)) { + $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from); + call_user_func_array($this->action_function, $params); + } + } +} + +/** + * PHPMailer exception handler + * @package PHPMailer + */ +class phpmailerException extends Exception +{ + /** + * Prettify error message output + * @return string + */ + public function errorMessage() + { + $errorMsg = '' . $this->getMessage() . "
\n"; + return $errorMsg; + } +} diff --git a/common/lib/class.popup.php b/common/lib/class.popup.php new file mode 100644 index 0000000..c5beed1 --- /dev/null +++ b/common/lib/class.popup.php @@ -0,0 +1,186 @@ +DB = $db; + } + + #팝업등록# + function set_popup_insert($argu){ + $data = array( + "p_title" => $argu['p_title'], + "p_content" => txtParse($argu["p_content"],1), + "p_use" => $argu['p_use'], + "p_top" => $argu['p_top'], + "p_left" => $argu['p_left'], + "p_width" => $argu['p_width'], + "p_height" => $argu['p_height'], + "p_regdate" => _NowTime, + "p_gubun" => $argu['p_gubun'] + ); + + $sth = $this->DB->autoPrepare(TABLE_POPUP, array_keys($data), DB_AUTOQUERY_INSERT); + $res = $this->DB->execute($sth, array_values($data)); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $p_idx=mysql_insert_id(); + + $data=array_merge($data,array("p_idx"=>$p_idx)); + + return $data; + + } + + + #팝업수정# + function set_popup_modify($argu){ + $data = array( + "p_title" => $argu['p_title'], + "p_content" => txtParse($argu["p_content"],1), + "p_use" => $argu['p_use'], + "p_top" => $argu['p_top'], + "p_left" => $argu['p_left'], + "p_width" => $argu['p_width'], + "p_height" => $argu['p_height'] + ); + + $res = $result = $this->DB->autoExecute(TABLE_POPUP, $data, DB_AUTOQUERY_UPDATE, " p_idx = '{$argu['p_idx']}' "); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + + #팝업삭제# + function set_popup_delete($p_idx){ + $query = "DELETE FROM ".TABLE_POPUP." WHERE p_idx = '".$p_idx."'"; + + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + + #팝업리스트삭제# + function set_popu_delete_list($argu){ + if(count($argu["chk"]) > 0){ + for($i = 0; $i < count($argu["chk"]); $i++){ + $p_idx = $argu["chk"][$i]; + $_list = $this -> set_popup_delete($p_idx); + } + return true; + } + else{ + go_url("","삭제할데이터가 없습니다."); + exit; + } + } + + + #팝업리스트# + function get_popup_list($argu,&$total,$limit = true){ + $addwhere = " where (1=1) and (p_gubun = '".$argu["gubun"]."')"; + + /// 검색쿼리 + if($argu['s_type']){ $addwhere .= " and {$argu['s_type']} like '%{$argu['keyword']}%' "; } + + $query = " + select + count(*) + from + ".TABLE_POPUP." + ".$addwhere; + + $res = $total = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = " + select + * + from + ".TABLE_POPUP." + ".$addwhere." + order by + p_regdate desc + "; + if($limit) + $query .= " + limit ".($argu['p']-1)*$this->_LIST_NUM.",".$this->_LIST_NUM; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + + } + + + #팝업상세보기 + function get_popup_view($p_idx){ + $query = "SELECT + * + FROM ".TABLE_POPUP." + where p_idx = '".$p_idx."'"; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $row; + + } + + + #팝업메인리스트# + function get_main_popup($lang){ + $addwhere = "WHERE (p_use = 'Y') and (p_gubun = '".$lang."') "; + + $query = "SELECT + p_idx + ,p_title + ,p_top + ,p_left + ,p_width + ,p_height + ,p_content + FROM ".TABLE_POPUP." + ".$addwhere." + ORDER BY p_regdate asc"; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + + } +?> \ No newline at end of file diff --git a/common/lib/class.portfolio.php b/common/lib/class.portfolio.php new file mode 100644 index 0000000..713de8a --- /dev/null +++ b/common/lib/class.portfolio.php @@ -0,0 +1,702 @@ +DB = $db; + $this->_PDS .= $this->_PDS_SUB; + $this->_T_PDS .= $this->_T_PDS_SUB; + $this->_B_PDS .= $this->_B_PDS_SUB; + } +#############카테고리S####################### + function set_category_insert($argu){ + $data = array( + "title" => $argu["title"], + "title_sub" => $argu["title_sub"], + "published" => ($argu["published"]=="Y")?"Y":"N", + ); + + $sth = $this->DB->autoPrepare(TABLE_CATEGORY, array_keys($data), DB_AUTOQUERY_INSERT); + $res = $this->DB->execute($sth, array_values($data)); + + if (DB::isError($res)) { + //debug($res); + go_url("", $res->getMessage()); + exit; + } + + $id=mysql_insert_id(); + + return true; + } + + function set_category_modify($argu){ + $data = array( + "title" => $argu["title"], + "title_sub" => $argu["title_sub"], + "published" => ($argu["published"]=="Y")?"Y":"N", + ); + $res = $result = $this->DB->autoExecute(TABLE_CATEGORY, $data, DB_AUTOQUERY_UPDATE, " id = '{$argu['id']}' "); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + # 목록 + function get_category_list($argu,&$total,$limit = true){ + global $_adminpage; + + $addwhere = "where (1=1) "; + if(!$_adminpage){$addwhere .= " and (published = 'Y') ";} + + if($argu['s_string']){$addwhere .= " and (title like '%{$argu['s_string']}%') "; } + + $query = " + select + count(*) + from + ".TABLE_CATEGORY." + ".$addwhere; + + $res = $total = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = " + select + * + from + ".TABLE_CATEGORY." + ".$addwhere." + order by id asc + "; + + if($argu["listnum"]){ + $_listnum = $argu["listnum"]; + } + else{ + $_listnum = $this->_LIST_NUM; + } + + if($limit) + $query .= " + limit ".($argu['p']-1)*$_listnum.",".$_listnum; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + + } + + function get_category_lnb(){ + global $_adminpage; + + $addwhere = "where (1=1) "; + $addwhere .= " and (published = 'Y') "; + + $query = " + select + * + from + ".TABLE_CATEGORY." + ".$addwhere." + order by id asc + "; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + + } + + function get_category_one(){ + + global $_adminpage; + + $addwhere = " where (1=1) "; + if(!$_adminpage) $addwhere .= "and (published = 'Y')"; + + $query = "SELECT + * + FROM ".TABLE_CATEGORY." + ".$addwhere." + ORDER BY id asc limit 0, 1"; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $row; + } + + + + #상세보기 + function get_category_view($id){ + $query = "SELECT + * + FROM ".TABLE_CATEGORY." + where id = '".$id."'"; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $row; + } + + #삭제# + function set_category_delete($id){ + + $query = "DELETE FROM ".TABLE_CATEGORY." WHERE id = '".$id."'"; + + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + $p_query = "DELETE FROM ".TABLE_PORTFOLIO." WHERE category = '".$id."'"; + + $p_res = $this->DB->query($query); + if (DB::isError($p_res)) { + go_url("", $p_res->getMessage()); + exit; + } + + return true; + } + +#############카테고리E####################### + + # 등록 + function set_insert($argu){ + //$res = $order_num = $this->DB->getOne("select ifnull(max(order_num),0)+1 from ".TABLE_PORTFOLIO." where category = '".$argu["category"]."'"); + $res = $order_num = $this->DB->getOne("select ifnull(max(order_num),0)+1 from ".TABLE_PORTFOLIO); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + + + //썸네일 업로드 + if($_FILES['thumb'] !== null && $_FILES['thumb'][error] == 0 && $_FILES['thumb'][size] > 0 ){ + $thumb_info = getimagesize($_FILES["thumb"]["tmp_name"]); + $thumb_width = $file_info[0]; //이미지 가로 사이즈 + $thumb_height = $file_info[1]; //이미지 세로 사이즈 + $thumb_type = $_FILES['thumb']['type']; + + if($thumb_width > 385){ + $thumb = thumb_upload($_FILES['thumb'],'/pds/portfolio/thumb/','T','385'); + } + else{ + $thumb = thumb_upload($_FILES['thumb'],'/pds/portfolio/thumb/','O',''); + } + } + + + $data = array( + "category" => $argu["category"], + "title" => $argu["title"], + "description" => strip_tags($argu["description"]), + "client" => $argu["client"], + "location" => $argu["location"], + "period" => $argu["period"], + "area" => $argu["area"], + "published" => ($argu["published"]=="Y")?"Y":"N", + "reg_date" => _NowTime, + "order_num" => $order_num, + "thumb" => $thumb, + "main" => ($argu["main"]=="Y")?"Y":"N", + ); + + $sth = $this->DB->autoPrepare(TABLE_PORTFOLIO, array_keys($data), DB_AUTOQUERY_INSERT); + $res = $this->DB->execute($sth, array_values($data)); + + if (DB::isError($res)) { + //debug($res); + go_url("", $res->getMessage()); + exit; + } + + $id=mysql_insert_id(); + + $files = array(); + foreach ($_FILES['images'] as $k => $l) { + foreach ($l as $i => $v) { + if (!array_key_exists($i, $files)) + $files[$i] = array(); + $files[$i][$k] = $v; + } + } + + foreach ($files as $file) { + $img_original[] = thumb_upload($file,'/pds/portfolio/','T','1088'); + } + + $images = json_encode($img_original); + $ordering = json_encode($argu["ordering"]); + $data_file = array( + "images" => $images, + "images_ordering" => $ordering + ); + + $res = $this->DB->autoExecute(TABLE_PORTFOLIO, $data_file, DB_AUTOQUERY_UPDATE, " id = '{$id}'"); + if (DB::isError($res)) { + //debug($res); + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + + #수정 + function set_modify($argu){ + + //썸네일 업로드 + if($_FILES['thumb'] !== null && $_FILES['thumb'][error] == 0 && $_FILES['thumb'][size] > 0 ){ + $thumb_info = getimagesize($_FILES["thumb"]["tmp_name"]); + $thumb_width = $file_info[0]; //이미지 가로 사이즈 + $thumb_height = $file_info[1]; //이미지 세로 사이즈 + $thumb_type = $_FILES['b_thumb']['type']; + + if($thumb_width > 385){ + $thumb = thumb_upload($_FILES['thumb'],'/pds/portfolio/thumb/','T','385',$argu["tmp_thumb"]); + } + else{ + $thumb = thumb_upload($_FILES['thumb'],'/pds/portfolio/thumb/','O','',$argu["tmp_thumb"]); + } + } + else{ + $thumb = $argu["tmp_thumb"]; + } + + + $data = array( + "category" => $argu["category"], + "title" => $argu["title"], + "description" => strip_tags($argu["description"]), + "client" => $argu["client"], + "location" => $argu["location"], + "period" => $argu["period"], + "area" => $argu["area"], + "published" => ($argu["published"]=="Y")?"Y":"N", + "thumb" => $thumb, + "main" => ($argu["main"]=="Y")?"Y":"N", + ); + $res = $result = $this->DB->autoExecute(TABLE_PORTFOLIO, $data, DB_AUTOQUERY_UPDATE, " id = '{$argu['id']}' "); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $files = array(); + foreach ($_FILES['images'] as $k => $l) { + foreach ($l as $i => $v) { + if (!array_key_exists($i, $files)) + $files[$i] = array(); + $files[$i][$k] = $v; + } + } + + $f=0; + foreach ($files as $file) { + $img_original[] = thumb_upload($file,'/pds/portfolio/','T','1457',$argu["tmp_image"][$f]); + $f++; + } + + $images = json_encode($img_original); + $ordering = json_encode($argu["ordering"]); + $data_file = array( + "images" => $images, + "images_ordering" => $ordering + ); + + $res = $this->DB->autoExecute(TABLE_PORTFOLIO, $data_file, DB_AUTOQUERY_UPDATE, " id = '{$argu['id']}'"); + if (DB::isError($res)) { + //debug($res); + go_url("", $res->getMessage()); + exit; + } + return true; + } + + # 목록 + function get_list($argu,&$total,$limit = true){ + global $_adminpage; + + $addwhere = "where (1=1) "; + if(!$_adminpage){$addwhere .= " and (published = 'Y') ";} + //if($_adminpage){$addwhere .= " and (category = '{$argu['category']}') ";} + if($argu['s_category']){$addwhere .= " and (category = '{$argu['s_category']}') ";} + + if($argu['Search']){ + $addwhere .= " and (title like '%{$argu['Search']}%'".$p_where.") "; + } + + if(!$_adminpage){ + $sort = " id desc"; + } + else{ + $sort = " id desc"; + } + + $query = " + select + count(*) + from + ".TABLE_PORTFOLIO." + ".$addwhere; + + $res = $total = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = " + select + *, + (select title from ".TABLE_CATEGORY." as c where c.id=category) as cate + from + ".TABLE_PORTFOLIO." + ".$addwhere." + order by ".$sort." + "; + + if($argu["listnum"]){ + $_listnum = $argu["listnum"]; + } + else{ + $_listnum = $this->_LIST_NUM; + } + + if($limit) + $query .= " + limit ".($argu['p']-1)*$_listnum.",".$_listnum; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + + } + + function get_list_limit($limit,$category,$id=""){ + global $_adminpage; + + $addwhere = "where (1=1) and (main='Y') "; + if(!$_adminpage){$addwhere .= " and (published = 'Y') ";} + if($id){$addwhere .= " and (id not in('".$id."')) ";} + if($argu['category']){$addwhere .= " and (category = '{$argu['category']}') ";} + + if(!$_adminpage){ + $sort = " event_date desc"; + } + else{ + $sort = " event_date desc"; + } + + + $query = " + select + *, + (select title from ".TABLE_CATEGORY." as c where c.id=category) as cate + from + ".TABLE_PORTFOLIO." + ".$addwhere." + order by ".$sort." + limit ".$limit." + "; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + + } + + + #상세보기 + function get_view($id){ + $query = "SELECT + *, + (select title from ".TABLE_CATEGORY." as c where c.id=category) as cate + FROM ".TABLE_PORTFOLIO." + where id = '".$id."'"; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $row; + } + + #삭제# + function set_delete($id){ + $_row = $this -> get_view($id); + + if($_row["thumb"]){ + if(file_exists($this->_T_PDS."/".$_row["thumb"])) unlink($this->_T_PDS."/".$_row["thumb"]); + } + + $images = json_decode($_row["images"]); + if(count($images) > 0){ + for($i=0;$i_PDS."/".$images[$i])) unlink($this->_PDS."/".$images[$i]); + } + } + + $query = "DELETE FROM ".TABLE_PORTFOLIO." WHERE id = '".$id."'"; + + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + } + + function get_total($argu) { + $addwhere = "where (1=1) "; + if(!$_adminpage){$addwhere .= " and (published = 'Y') ";} + if($argu['s_category']){$addwhere .= " and (category = '{$argu['s_category']}') ";} + + + $query = " + select + count(*) + from + ".TABLE_PORTFOLIO." + ".$addwhere; + + $res = $total = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $total; + } + + //진열순서변경 + function set_order_modify($argu){ + $data = array( + "order_num" => $argu["order_num"] + ); + $res = $this->DB->autoExecute(TABLE_PORTFOLIO, $data, DB_AUTOQUERY_UPDATE, " id = '{$argu['id']}' "); + if (DB::isError($res)) { + //debug($res); + go_url("",$res->getMessage()); + exit; + } + + return true; + } + + + /***** + * 이전 게시물 정보를 가져온다. + *****/ + function get_prev($id, $category='', $search=''){ + // TODO : 답변형의 경우 정확한 이전정보 가져오는 방법을 생각해보자 + global $_adminpage; + $addwhere = ""; + if($category){ + $addwhere = " and (category='".$category."')"; + } + + if($search){ + $addwhere .= " and (title like '%{$argu['Search']}%') "; + } + + $query = " + select + * + from + ".TABLE_PORTFOLIO." + where + id > '{$id}' + $addwhere + order by + id asc + limit 1 + "; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + //debug($res); + //go_url("", $res->getMessage()); + return false; + exit; + } + return $row; + } + + /***** + * 다음 게시물 정보를 가져온다. + *****/ + function get_next($id, $category='', $search=''){ + // TODO : 답변형의 경우 정확한 다음정보 가져오는 방법을 생각해보자 + global $_adminpage; + $addwhere = ""; + if($category){ + $addwhere = " and (category='".$category."')"; + } + + if($search){ + $addwhere .= " and (title like '%{$argu['Search']}%') "; + } + + $query = " + select + * + from + ".TABLE_PORTFOLIO." + where + id < '{$id}' + $addwhere + order by + id desc + limit 1 + "; + + $res = $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($row)) { + //debug($res); + //go_url("", $res->getMessage()); + return false; + exit; + } + return $row; + } + + + function set_order($argu){ + + if($argu["s_mode"] == "up"){ + + //$res = $id = $this->DB->getOne("select id from ".TABLE_PORTFOLIO." where (order_num < '".$argu["order_num"]."') and (category = '".$argu["category"]."') order by order_num desc limit 1"); + $res = $id = $this->DB->getOne("select id from ".TABLE_PORTFOLIO." where (order_num < '".$argu["order_num"]."') order by order_num desc limit 1"); + + if($id){ + + $query = " + update ".TABLE_PORTFOLIO." + set + order_num = order_num - 1 + where + id = '".$argu["id"]."' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query1 = " + update ".TABLE_PORTFOLIO." + set + order_num = order_num + 1 + where + id = '".$id."' + "; + + $res1 = $this->DB->query($query1); + if (DB::isError($res1)) { + go_url("", $res1->getMessage()); + exit; + } + + } + else{ + go_url("", "정열값이 최상위 입니다."); + exit; + } + + } + else if($argu["s_mode"] == "down"){ + //$res = $id = $this->DB->getOne("select id from ".TABLE_PORTFOLIO." where (order_num > '".$argu["order_num"]."')and (category = '".$argu["category"]."') order by order_num asc limit 1"); + $res = $id = $this->DB->getOne("select id from ".TABLE_PORTFOLIO." where (order_num > '".$argu["order_num"]."') order by order_num asc limit 1"); + + if($id){ + + $query = " + update ".TABLE_PORTFOLIO." + set + order_num = order_num + 1 + where + id = '".$argu["id"]."' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query1 = " + update ".TABLE_PORTFOLIO." + set + order_num = order_num - 1 + where + id = '".$id."' + "; + + $res1 = $this->DB->query($query1); + if (DB::isError($res1)) { + go_url("", $res1->getMessage()); + exit; + } + + } + else{ + go_url("", "정열값이 최하위 입니다."); + exit; + } + } + + return true; + } +} +?> \ No newline at end of file diff --git a/common/lib/class.smtp.php b/common/lib/class.smtp.php new file mode 100644 index 0000000..17444ef --- /dev/null +++ b/common/lib/class.smtp.php @@ -0,0 +1,1181 @@ + + * @author Jim Jagielski (jimjag) + * @author Andy Prevost (codeworxtech) + * @author Brent R. Matzelle (original founder) + * @copyright 2014 Marcus Bointon + * @copyright 2010 - 2012 Jim Jagielski + * @copyright 2004 - 2009 Andy Prevost + * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License + * @note This program is distributed in the hope that it will be useful - WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + */ + +/** + * PHPMailer RFC821 SMTP email transport class. + * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server. + * @package PHPMailer + * @author Chris Ryan + * @author Marcus Bointon + */ +class SMTP +{ + /** + * The PHPMailer SMTP version number. + * @var string + */ + const VERSION = '5.2.14'; + + /** + * SMTP line break constant. + * @var string + */ + const CRLF = "\r\n"; + + /** + * The SMTP port to use if one is not specified. + * @var integer + */ + const DEFAULT_SMTP_PORT = 25; + + /** + * The maximum line length allowed by RFC 2822 section 2.1.1 + * @var integer + */ + const MAX_LINE_LENGTH = 998; + + /** + * Debug level for no output + */ + const DEBUG_OFF = 0; + + /** + * Debug level to show client -> server messages + */ + const DEBUG_CLIENT = 1; + + /** + * Debug level to show client -> server and server -> client messages + */ + const DEBUG_SERVER = 2; + + /** + * Debug level to show connection status, client -> server and server -> client messages + */ + const DEBUG_CONNECTION = 3; + + /** + * Debug level to show all messages + */ + const DEBUG_LOWLEVEL = 4; + + /** + * The PHPMailer SMTP Version number. + * @var string + * @deprecated Use the `VERSION` constant instead + * @see SMTP::VERSION + */ + public $Version = '5.2.14'; + + /** + * SMTP server port number. + * @var integer + * @deprecated This is only ever used as a default value, so use the `DEFAULT_SMTP_PORT` constant instead + * @see SMTP::DEFAULT_SMTP_PORT + */ + public $SMTP_PORT = 25; + + /** + * SMTP reply line ending. + * @var string + * @deprecated Use the `CRLF` constant instead + * @see SMTP::CRLF + */ + public $CRLF = "\r\n"; + + /** + * Debug output level. + * Options: + * * self::DEBUG_OFF (`0`) No debug output, default + * * self::DEBUG_CLIENT (`1`) Client commands + * * self::DEBUG_SERVER (`2`) Client commands and server responses + * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status + * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages + * @var integer + */ + public $do_debug = self::DEBUG_OFF; + + /** + * How to handle debug output. + * Options: + * * `echo` Output plain-text as-is, appropriate for CLI + * * `html` Output escaped, line breaks converted to `
`, appropriate for browser output + * * `error_log` Output to error log as configured in php.ini + * + * Alternatively, you can provide a callable expecting two params: a message string and the debug level: + * + * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";}; + * + * @var string|callable + */ + public $Debugoutput = 'echo'; + + /** + * Whether to use VERP. + * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path + * @link http://www.postfix.org/VERP_README.html Info on VERP + * @var boolean + */ + public $do_verp = false; + + /** + * The timeout value for connection, in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure. + * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2 + * @var integer + */ + public $Timeout = 300; + + /** + * How long to wait for commands to complete, in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * @var integer + */ + public $Timelimit = 300; + + /** + * The socket for the server connection. + * @var resource + */ + protected $smtp_conn; + + /** + * Error information, if any, for the last SMTP command. + * @var array + */ + protected $error = array( + 'error' => '', + 'detail' => '', + 'smtp_code' => '', + 'smtp_code_ex' => '' + ); + + /** + * The reply the server sent to us for HELO. + * If null, no HELO string has yet been received. + * @var string|null + */ + protected $helo_rply = null; + + /** + * The set of SMTP extensions sent in reply to EHLO command. + * Indexes of the array are extension names. + * Value at index 'HELO' or 'EHLO' (according to command that was sent) + * represents the server name. In case of HELO it is the only element of the array. + * Other values can be boolean TRUE or an array containing extension options. + * If null, no HELO/EHLO string has yet been received. + * @var array|null + */ + protected $server_caps = null; + + /** + * The most recent reply received from the server. + * @var string + */ + protected $last_reply = ''; + + /** + * Output debugging info via a user-selected method. + * @see SMTP::$Debugoutput + * @see SMTP::$do_debug + * @param string $str Debug string to output + * @param integer $level The debug level of this message; see DEBUG_* constants + * @return void + */ + protected function edebug($str, $level = 0) + { + if ($level > $this->do_debug) { + return; + } + //Avoid clash with built-in function names + if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) { + call_user_func($this->Debugoutput, $str, $this->do_debug); + return; + } + switch ($this->Debugoutput) { + case 'error_log': + //Don't output, just log + error_log($str); + break; + case 'html': + //Cleans up output a bit for a better looking, HTML-safe output + echo htmlentities( + preg_replace('/[\r\n]+/', '', $str), + ENT_QUOTES, + 'UTF-8' + ) + . "
\n"; + break; + case 'echo': + default: + //Normalize line breaks + $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str); + echo gmdate('Y-m-d H:i:s') . "\t" . str_replace( + "\n", + "\n \t ", + trim($str) + )."\n"; + } + } + + /** + * Connect to an SMTP server. + * @param string $host SMTP server IP or host name + * @param integer $port The port number to connect to + * @param integer $timeout How long to wait for the connection to open + * @param array $options An array of options for stream_context_create() + * @access public + * @return boolean + */ + public function connect($host, $port = null, $timeout = 30, $options = array()) + { + static $streamok; + //This is enabled by default since 5.0.0 but some providers disable it + //Check this once and cache the result + if (is_null($streamok)) { + $streamok = function_exists('stream_socket_client'); + } + // Clear errors to avoid confusion + $this->setError(''); + // Make sure we are __not__ connected + if ($this->connected()) { + // Already connected, generate error + $this->setError('Already connected to a server'); + return false; + } + if (empty($port)) { + $port = self::DEFAULT_SMTP_PORT; + } + // Connect to the SMTP server + $this->edebug( + "Connection: opening to $host:$port, timeout=$timeout, options=".var_export($options, true), + self::DEBUG_CONNECTION + ); + $errno = 0; + $errstr = ''; + if ($streamok) { + $socket_context = stream_context_create($options); + //Suppress errors; connection failures are handled at a higher level + $this->smtp_conn = @stream_socket_client( + $host . ":" . $port, + $errno, + $errstr, + $timeout, + STREAM_CLIENT_CONNECT, + $socket_context + ); + } else { + //Fall back to fsockopen which should work in more places, but is missing some features + $this->edebug( + "Connection: stream_socket_client not available, falling back to fsockopen", + self::DEBUG_CONNECTION + ); + $this->smtp_conn = fsockopen( + $host, + $port, + $errno, + $errstr, + $timeout + ); + } + // Verify we connected properly + if (!is_resource($this->smtp_conn)) { + $this->setError( + 'Failed to connect to server', + $errno, + $errstr + ); + $this->edebug( + 'SMTP ERROR: ' . $this->error['error'] + . ": $errstr ($errno)", + self::DEBUG_CLIENT + ); + return false; + } + $this->edebug('Connection: opened', self::DEBUG_CONNECTION); + // SMTP server can take longer to respond, give longer timeout for first read + // Windows does not have support for this timeout function + if (substr(PHP_OS, 0, 3) != 'WIN') { + $max = ini_get('max_execution_time'); + // Don't bother if unlimited + if ($max != 0 && $timeout > $max) { + @set_time_limit($timeout); + } + stream_set_timeout($this->smtp_conn, $timeout, 0); + } + // Get any announcement + $announce = $this->get_lines(); + $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER); + return true; + } + + /** + * Initiate a TLS (encrypted) session. + * @access public + * @return boolean + */ + public function startTLS() + { + if (!$this->sendCommand('STARTTLS', 'STARTTLS', 220)) { + return false; + } + // Begin encrypted connection + if (!stream_socket_enable_crypto( + $this->smtp_conn, + true, + STREAM_CRYPTO_METHOD_TLS_CLIENT + )) { + return false; + } + return true; + } + + /** + * Perform SMTP authentication. + * Must be run after hello(). + * @see hello() + * @param string $username The user name + * @param string $password The password + * @param string $authtype The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5, XOAUTH2) + * @param string $realm The auth realm for NTLM + * @param string $workstation The auth workstation for NTLM + * @param null|OAuth $OAuth An optional OAuth instance (@see PHPMailerOAuth) + * @return bool True if successfully authenticated.* @access public + */ + public function authenticate( + $username, + $password, + $authtype = null, + $realm = '', + $workstation = '', + $OAuth = null + ) { + if (!$this->server_caps) { + $this->setError('Authentication is not allowed before HELO/EHLO'); + return false; + } + + if (array_key_exists('EHLO', $this->server_caps)) { + // SMTP extensions are available. Let's try to find a proper authentication method + + if (!array_key_exists('AUTH', $this->server_caps)) { + $this->setError('Authentication is not allowed at this stage'); + // 'at this stage' means that auth may be allowed after the stage changes + // e.g. after STARTTLS + return false; + } + + self::edebug('Auth method requested: ' . ($authtype ? $authtype : 'UNKNOWN'), self::DEBUG_LOWLEVEL); + self::edebug( + 'Auth methods available on the server: ' . implode(',', $this->server_caps['AUTH']), + self::DEBUG_LOWLEVEL + ); + + if (empty($authtype)) { + foreach (array('LOGIN', 'CRAM-MD5', 'NTLM', 'PLAIN', 'XOAUTH2') as $method) { + if (in_array($method, $this->server_caps['AUTH'])) { + $authtype = $method; + break; + } + } + if (empty($authtype)) { + $this->setError('No supported authentication methods found'); + return false; + } + self::edebug('Auth method selected: '.$authtype, self::DEBUG_LOWLEVEL); + } + + if (!in_array($authtype, $this->server_caps['AUTH'])) { + $this->setError("The requested authentication method \"$authtype\" is not supported by the server"); + return false; + } + } elseif (empty($authtype)) { + $authtype = 'LOGIN'; + } + switch ($authtype) { + case 'PLAIN': + // Start authentication + if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) { + return false; + } + // Send encoded username and password + if (!$this->sendCommand( + 'User & Password', + base64_encode("\0" . $username . "\0" . $password), + 235 + ) + ) { + return false; + } + break; + case 'LOGIN': + // Start authentication + if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) { + return false; + } + if (!$this->sendCommand("Username", base64_encode($username), 334)) { + return false; + } + if (!$this->sendCommand("Password", base64_encode($password), 235)) { + return false; + } + break; + case 'XOAUTH2': + //If the OAuth Instance is not set. Can be a case when PHPMailer is used + //instead of PHPMailerOAuth + if (is_null($OAuth)) { + return false; + } + $oauth = $OAuth->getOauth64(); + + // Start authentication + if (!$this->sendCommand('AUTH', 'AUTH XOAUTH2 ' . $oauth, 235)) { + return false; + } + break; + case 'NTLM': + /* + * ntlm_sasl_client.php + * Bundled with Permission + * + * How to telnet in windows: + * http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx + * PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication + */ + require_once 'extras/ntlm_sasl_client.php'; + $temp = new stdClass; + $ntlm_client = new ntlm_sasl_client_class; + //Check that functions are available + if (!$ntlm_client->Initialize($temp)) { + $this->setError($temp->error); + $this->edebug( + 'You need to enable some modules in your php.ini file: ' + . $this->error['error'], + self::DEBUG_CLIENT + ); + return false; + } + //msg1 + $msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1 + + if (!$this->sendCommand( + 'AUTH NTLM', + 'AUTH NTLM ' . base64_encode($msg1), + 334 + ) + ) { + return false; + } + //Though 0 based, there is a white space after the 3 digit number + //msg2 + $challenge = substr($this->last_reply, 3); + $challenge = base64_decode($challenge); + $ntlm_res = $ntlm_client->NTLMResponse( + substr($challenge, 24, 8), + $password + ); + //msg3 + $msg3 = $ntlm_client->TypeMsg3( + $ntlm_res, + $username, + $realm, + $workstation + ); + // send encoded username + return $this->sendCommand('Username', base64_encode($msg3), 235); + case 'CRAM-MD5': + // Start authentication + if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) { + return false; + } + // Get the challenge + $challenge = base64_decode(substr($this->last_reply, 4)); + + // Build the response + $response = $username . ' ' . $this->hmac($challenge, $password); + + // send encoded credentials + return $this->sendCommand('Username', base64_encode($response), 235); + default: + $this->setError("Authentication method \"$authtype\" is not supported"); + return false; + } + return true; + } + + /** + * Calculate an MD5 HMAC hash. + * Works like hash_hmac('md5', $data, $key) + * in case that function is not available + * @param string $data The data to hash + * @param string $key The key to hash with + * @access protected + * @return string + */ + protected function hmac($data, $key) + { + if (function_exists('hash_hmac')) { + return hash_hmac('md5', $data, $key); + } + + // The following borrowed from + // http://php.net/manual/en/function.mhash.php#27225 + + // RFC 2104 HMAC implementation for php. + // Creates an md5 HMAC. + // Eliminates the need to install mhash to compute a HMAC + // by Lance Rushing + + $bytelen = 64; // byte length for md5 + if (strlen($key) > $bytelen) { + $key = pack('H*', md5($key)); + } + $key = str_pad($key, $bytelen, chr(0x00)); + $ipad = str_pad('', $bytelen, chr(0x36)); + $opad = str_pad('', $bytelen, chr(0x5c)); + $k_ipad = $key ^ $ipad; + $k_opad = $key ^ $opad; + + return md5($k_opad . pack('H*', md5($k_ipad . $data))); + } + + /** + * Check connection state. + * @access public + * @return boolean True if connected. + */ + public function connected() + { + if (is_resource($this->smtp_conn)) { + $sock_status = stream_get_meta_data($this->smtp_conn); + if ($sock_status['eof']) { + // The socket is valid but we are not connected + $this->edebug( + 'SMTP NOTICE: EOF caught while checking if connected', + self::DEBUG_CLIENT + ); + $this->close(); + return false; + } + return true; // everything looks good + } + return false; + } + + /** + * Close the socket and clean up the state of the class. + * Don't use this function without first trying to use QUIT. + * @see quit() + * @access public + * @return void + */ + public function close() + { + $this->setError(''); + $this->server_caps = null; + $this->helo_rply = null; + if (is_resource($this->smtp_conn)) { + // close the connection and cleanup + fclose($this->smtp_conn); + $this->smtp_conn = null; //Makes for cleaner serialization + $this->edebug('Connection: closed', self::DEBUG_CONNECTION); + } + } + + /** + * Send an SMTP DATA command. + * Issues a data command and sends the msg_data to the server, + * finializing the mail transaction. $msg_data is the message + * that is to be send with the headers. Each header needs to be + * on a single line followed by a with the message headers + * and the message body being separated by and additional . + * Implements rfc 821: DATA + * @param string $msg_data Message data to send + * @access public + * @return boolean + */ + public function data($msg_data) + { + //This will use the standard timelimit + if (!$this->sendCommand('DATA', 'DATA', 354)) { + return false; + } + + /* The server is ready to accept data! + * According to rfc821 we should not send more than 1000 characters on a single line (including the CRLF) + * so we will break the data up into lines by \r and/or \n then if needed we will break each of those into + * smaller lines to fit within the limit. + * We will also look for lines that start with a '.' and prepend an additional '.'. + * NOTE: this does not count towards line-length limit. + */ + + // Normalize line breaks before exploding + $lines = explode("\n", str_replace(array("\r\n", "\r"), "\n", $msg_data)); + + /* To distinguish between a complete RFC822 message and a plain message body, we check if the first field + * of the first line (':' separated) does not contain a space then it _should_ be a header and we will + * process all lines before a blank line as headers. + */ + + $field = substr($lines[0], 0, strpos($lines[0], ':')); + $in_headers = false; + if (!empty($field) && strpos($field, ' ') === false) { + $in_headers = true; + } + + foreach ($lines as $line) { + $lines_out = array(); + if ($in_headers and $line == '') { + $in_headers = false; + } + //Break this line up into several smaller lines if it's too long + //Micro-optimisation: isset($str[$len]) is faster than (strlen($str) > $len), + while (isset($line[self::MAX_LINE_LENGTH])) { + //Working backwards, try to find a space within the last MAX_LINE_LENGTH chars of the line to break on + //so as to avoid breaking in the middle of a word + $pos = strrpos(substr($line, 0, self::MAX_LINE_LENGTH), ' '); + //Deliberately matches both false and 0 + if (!$pos) { + //No nice break found, add a hard break + $pos = self::MAX_LINE_LENGTH - 1; + $lines_out[] = substr($line, 0, $pos); + $line = substr($line, $pos); + } else { + //Break at the found point + $lines_out[] = substr($line, 0, $pos); + //Move along by the amount we dealt with + $line = substr($line, $pos + 1); + } + //If processing headers add a LWSP-char to the front of new line RFC822 section 3.1.1 + if ($in_headers) { + $line = "\t" . $line; + } + } + $lines_out[] = $line; + + //Send the lines to the server + foreach ($lines_out as $line_out) { + //RFC2821 section 4.5.2 + if (!empty($line_out) and $line_out[0] == '.') { + $line_out = '.' . $line_out; + } + $this->client_send($line_out . self::CRLF); + } + } + + //Message data has been sent, complete the command + //Increase timelimit for end of DATA command + $savetimelimit = $this->Timelimit; + $this->Timelimit = $this->Timelimit * 2; + $result = $this->sendCommand('DATA END', '.', 250); + //Restore timelimit + $this->Timelimit = $savetimelimit; + return $result; + } + + /** + * Send an SMTP HELO or EHLO command. + * Used to identify the sending server to the receiving server. + * This makes sure that client and server are in a known state. + * Implements RFC 821: HELO + * and RFC 2821 EHLO. + * @param string $host The host name or IP to connect to + * @access public + * @return boolean + */ + public function hello($host = '') + { + //Try extended hello first (RFC 2821) + return (boolean)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host)); + } + + /** + * Send an SMTP HELO or EHLO command. + * Low-level implementation used by hello() + * @see hello() + * @param string $hello The HELO string + * @param string $host The hostname to say we are + * @access protected + * @return boolean + */ + protected function sendHello($hello, $host) + { + $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250); + $this->helo_rply = $this->last_reply; + if ($noerror) { + $this->parseHelloFields($hello); + } else { + $this->server_caps = null; + } + return $noerror; + } + + /** + * Parse a reply to HELO/EHLO command to discover server extensions. + * In case of HELO, the only parameter that can be discovered is a server name. + * @access protected + * @param string $type - 'HELO' or 'EHLO' + */ + protected function parseHelloFields($type) + { + $this->server_caps = array(); + $lines = explode("\n", $this->helo_rply); + + foreach ($lines as $n => $s) { + //First 4 chars contain response code followed by - or space + $s = trim(substr($s, 4)); + if (empty($s)) { + continue; + } + $fields = explode(' ', $s); + if (!empty($fields)) { + if (!$n) { + $name = $type; + $fields = $fields[0]; + } else { + $name = array_shift($fields); + switch ($name) { + case 'SIZE': + $fields = ($fields ? $fields[0] : 0); + break; + case 'AUTH': + if (!is_array($fields)) { + $fields = array(); + } + break; + default: + $fields = true; + } + } + $this->server_caps[$name] = $fields; + } + } + } + + /** + * Send an SMTP MAIL command. + * Starts a mail transaction from the email address specified in + * $from. Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more recipient + * commands may be called followed by a data command. + * Implements rfc 821: MAIL FROM: + * @param string $from Source address of this message + * @access public + * @return boolean + */ + public function mail($from) + { + $useVerp = ($this->do_verp ? ' XVERP' : ''); + return $this->sendCommand( + 'MAIL FROM', + 'MAIL FROM:<' . $from . '>' . $useVerp, + 250 + ); + } + + /** + * Send an SMTP QUIT command. + * Closes the socket if there is no error or the $close_on_error argument is true. + * Implements from rfc 821: QUIT + * @param boolean $close_on_error Should the connection close if an error occurs? + * @access public + * @return boolean + */ + public function quit($close_on_error = true) + { + $noerror = $this->sendCommand('QUIT', 'QUIT', 221); + $err = $this->error; //Save any error + if ($noerror or $close_on_error) { + $this->close(); + $this->error = $err; //Restore any error from the quit command + } + return $noerror; + } + + /** + * Send an SMTP RCPT command. + * Sets the TO argument to $toaddr. + * Returns true if the recipient was accepted false if it was rejected. + * Implements from rfc 821: RCPT TO: + * @param string $address The address the message is being sent to + * @access public + * @return boolean + */ + public function recipient($address) + { + return $this->sendCommand( + 'RCPT TO', + 'RCPT TO:<' . $address . '>', + array(250, 251) + ); + } + + /** + * Send an SMTP RSET command. + * Abort any transaction that is currently in progress. + * Implements rfc 821: RSET + * @access public + * @return boolean True on success. + */ + public function reset() + { + return $this->sendCommand('RSET', 'RSET', 250); + } + + /** + * Send a command to an SMTP server and check its return code. + * @param string $command The command name - not sent to the server + * @param string $commandstring The actual command to send + * @param integer|array $expect One or more expected integer success codes + * @access protected + * @return boolean True on success. + */ + protected function sendCommand($command, $commandstring, $expect) + { + if (!$this->connected()) { + $this->setError("Called $command without being connected"); + return false; + } + //Reject line breaks in all commands + if (strpos($commandstring, "\n") !== false or strpos($commandstring, "\r") !== false) { + $this->setError("Command '$command' contained line breaks"); + return false; + } + $this->client_send($commandstring . self::CRLF); + + $this->last_reply = $this->get_lines(); + // Fetch SMTP code and possible error code explanation + $matches = array(); + if (preg_match("/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/", $this->last_reply, $matches)) { + $code = $matches[1]; + $code_ex = (count($matches) > 2 ? $matches[2] : null); + // Cut off error code from each response line + $detail = preg_replace( + "/{$code}[ -]".($code_ex ? str_replace('.', '\\.', $code_ex).' ' : '')."/m", + '', + $this->last_reply + ); + } else { + // Fall back to simple parsing if regex fails + $code = substr($this->last_reply, 0, 3); + $code_ex = null; + $detail = substr($this->last_reply, 4); + } + + $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER); + + if (!in_array($code, (array)$expect)) { + $this->setError( + "$command command failed", + $detail, + $code, + $code_ex + ); + $this->edebug( + 'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply, + self::DEBUG_CLIENT + ); + return false; + } + + $this->setError(''); + return true; + } + + /** + * Send an SMTP SAML command. + * Starts a mail transaction from the email address specified in $from. + * Returns true if successful or false otherwise. If True + * the mail transaction is started and then one or more recipient + * commands may be called followed by a data command. This command + * will send the message to the users terminal if they are logged + * in and send them an email. + * Implements rfc 821: SAML FROM: + * @param string $from The address the message is from + * @access public + * @return boolean + */ + public function sendAndMail($from) + { + return $this->sendCommand('SAML', "SAML FROM:$from", 250); + } + + /** + * Send an SMTP VRFY command. + * @param string $name The name to verify + * @access public + * @return boolean + */ + public function verify($name) + { + return $this->sendCommand('VRFY', "VRFY $name", array(250, 251)); + } + + /** + * Send an SMTP NOOP command. + * Used to keep keep-alives alive, doesn't actually do anything + * @access public + * @return boolean + */ + public function noop() + { + return $this->sendCommand('NOOP', 'NOOP', 250); + } + + /** + * Send an SMTP TURN command. + * This is an optional command for SMTP that this class does not support. + * This method is here to make the RFC821 Definition complete for this class + * and _may_ be implemented in future + * Implements from rfc 821: TURN + * @access public + * @return boolean + */ + public function turn() + { + $this->setError('The SMTP TURN command is not implemented'); + $this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT); + return false; + } + + /** + * Send raw data to the server. + * @param string $data The data to send + * @access public + * @return integer|boolean The number of bytes sent to the server or false on error + */ + public function client_send($data) + { + $this->edebug("CLIENT -> SERVER: $data", self::DEBUG_CLIENT); + return fwrite($this->smtp_conn, $data); + } + + /** + * Get the latest error. + * @access public + * @return array + */ + public function getError() + { + return $this->error; + } + + /** + * Get SMTP extensions available on the server + * @access public + * @return array|null + */ + public function getServerExtList() + { + return $this->server_caps; + } + + /** + * A multipurpose method + * The method works in three ways, dependent on argument value and current state + * 1. HELO/EHLO was not sent - returns null and set up $this->error + * 2. HELO was sent + * $name = 'HELO': returns server name + * $name = 'EHLO': returns boolean false + * $name = any string: returns null and set up $this->error + * 3. EHLO was sent + * $name = 'HELO'|'EHLO': returns server name + * $name = any string: if extension $name exists, returns boolean True + * or its options. Otherwise returns boolean False + * In other words, one can use this method to detect 3 conditions: + * - null returned: handshake was not or we don't know about ext (refer to $this->error) + * - false returned: the requested feature exactly not exists + * - positive value returned: the requested feature exists + * @param string $name Name of SMTP extension or 'HELO'|'EHLO' + * @return mixed + */ + public function getServerExt($name) + { + if (!$this->server_caps) { + $this->setError('No HELO/EHLO was sent'); + return null; + } + + // the tight logic knot ;) + if (!array_key_exists($name, $this->server_caps)) { + if ($name == 'HELO') { + return $this->server_caps['EHLO']; + } + if ($name == 'EHLO' || array_key_exists('EHLO', $this->server_caps)) { + return false; + } + $this->setError('HELO handshake was used. Client knows nothing about server extensions'); + return null; + } + + return $this->server_caps[$name]; + } + + /** + * Get the last reply from the server. + * @access public + * @return string + */ + public function getLastReply() + { + return $this->last_reply; + } + + /** + * Read the SMTP server's response. + * Either before eof or socket timeout occurs on the operation. + * With SMTP we can tell if we have more lines to read if the + * 4th character is '-' symbol. If it is a space then we don't + * need to read anything else. + * @access protected + * @return string + */ + protected function get_lines() + { + // If the connection is bad, give up straight away + if (!is_resource($this->smtp_conn)) { + return ''; + } + $data = ''; + $endtime = 0; + stream_set_timeout($this->smtp_conn, $this->Timeout); + if ($this->Timelimit > 0) { + $endtime = time() + $this->Timelimit; + } + while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) { + $str = @fgets($this->smtp_conn, 515); + $this->edebug("SMTP -> get_lines(): \$data is \"$data\"", self::DEBUG_LOWLEVEL); + $this->edebug("SMTP -> get_lines(): \$str is \"$str\"", self::DEBUG_LOWLEVEL); + $data .= $str; + // If 4th character is a space, we are done reading, break the loop, micro-optimisation over strlen + if ((isset($str[3]) and $str[3] == ' ')) { + break; + } + // Timed-out? Log and break + $info = stream_get_meta_data($this->smtp_conn); + if ($info['timed_out']) { + $this->edebug( + 'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)', + self::DEBUG_LOWLEVEL + ); + break; + } + // Now check if reads took too long + if ($endtime and time() > $endtime) { + $this->edebug( + 'SMTP -> get_lines(): timelimit reached ('. + $this->Timelimit . ' sec)', + self::DEBUG_LOWLEVEL + ); + break; + } + } + return $data; + } + + /** + * Enable or disable VERP address generation. + * @param boolean $enabled + */ + public function setVerp($enabled = false) + { + $this->do_verp = $enabled; + } + + /** + * Get VERP address generation mode. + * @return boolean + */ + public function getVerp() + { + return $this->do_verp; + } + + /** + * Set error messages and codes. + * @param string $message The error message + * @param string $detail Further detail on the error + * @param string $smtp_code An associated SMTP error code + * @param string $smtp_code_ex Extended SMTP code + */ + protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '') + { + $this->error = array( + 'error' => $message, + 'detail' => $detail, + 'smtp_code' => $smtp_code, + 'smtp_code_ex' => $smtp_code_ex + ); + } + + /** + * Set debug output method. + * @param string|callable $method The name of the mechanism to use for debugging output, or a callable to handle it. + */ + public function setDebugOutput($method = 'echo') + { + $this->Debugoutput = $method; + } + + /** + * Get debug output method. + * @return string + */ + public function getDebugOutput() + { + return $this->Debugoutput; + } + + /** + * Set debug output level. + * @param integer $level + */ + public function setDebugLevel($level = 0) + { + $this->do_debug = $level; + } + + /** + * Get debug output level. + * @return integer + */ + public function getDebugLevel() + { + return $this->do_debug; + } + + /** + * Set SMTP timeout. + * @param integer $timeout + */ + public function setTimeout($timeout = 0) + { + $this->Timeout = $timeout; + } + + /** + * Get SMTP timeout. + * @return integer + */ + public function getTimeout() + { + return $this->Timeout; + } +} diff --git a/common/lib/class.user.php b/common/lib/class.user.php new file mode 100644 index 0000000..658fca2 --- /dev/null +++ b/common/lib/class.user.php @@ -0,0 +1,679 @@ +DB = $db; + } + + /***** + * 세션정보로서 관리자 권한을 가지고 있는지 확인 한다. + * "user_id" 세션값이 존재하고 "user_level" 세션값이 지정한 값보다 같거나 작은지 확인한다. + *****/ + function check_admin($info){ + return ($info['user_no'] != null && $info['user_id'] != null && $info['user_level'] <= $this->user_admin_level)? true:false; + } + + /***** + * 세션정보로서 직원 권한을 가지고 있는지 확인 한다. + * "user_id" 세션값이 존재하고 "user_level" 세션값이 지정한 값보다 같거나 작은지 확인한다. + *****/ + function check_staff($info){ + return ($info['user_no'] != null && $info['user_id'] != null && $info['user_level'] <= $this->user_manager_level)? true:false; + } + + /***** + * 세션정보로서 정회원 권한을 가지고 있는지 확인 한다. + * "user_id" 세션값이 존재하고 "user_level" 세션값이 지정한 값보다 같거나 작은지 확인한다. + *****/ + function check_regular($info){ + return ($info['user_no'] != null && $info['user_id'] != null && $info['user_level'] <= $this->user_regular_level)? true:false; + } + + /***** + * 세션정보로서 로그인 상태인지 확인 한다. + * "user_id" 세션값이 존재하고 "user_level" 세션값이 지정한 값보다 작은지 확인한다. + *****/ + function check_login($info){ + return ($info['user_no'] != null && $info['user_id'] != null && $info['user_level'] <= $this->user_basic_level)? true:false; + } + + /***** + * 아이디 중복체크 + * 기본 검사는 javascript 와 php 에서 동시에 처리할 수 도 있으니 기본 검사 방법이 변경이 된다면 두군대를 수정하여야 한다. + *****/ + function check_dupleid($str){ + // Rule - 아이디는 4~10 자리 이며 첫자리에는 숫자가 올수없고 영숫자 조합이고 소문자만 사용한다. + //if(ereg('^[a-z]{1}[a-z0-9]{3,11}$', $str)){ + //if(preg_match(_REGEXP, $str)){ + if($this->DB->getOne("select count(*) from ".TABLE_USER." where user_id = '{$str}'") > 0){ // 중복 아이디일 경우 + return array("code" => "D","user_id" => $str); + }else{ // 중복 아이디가 아닐경우 + return array("code" => "A","user_id" => $str); + } + //}else{ // 형식에 맞지 않을경우 + // return array("code" => "F","user_id" => ""); + //} + } + + /***** + * 입력정보를 통해 회원 여부를 확인한다. + *****/ + function check_login_info($argu){ + $pwd1=substr(md5($argu["user_pwd"]),0,20); + $pwd2=substr(md5($argu["user_pwd"]),-20); + + $pwd=$pwd1.$pwd2; + + $query = " + select + u.user_no, + u.user_id, + u.user_name, + u.user_level, + u.user_withdrawal + from + ".TABLE_USER." u + where + u.user_id = /* 1 */ ? + and u.user_pwd = /* 2 */ ? + "; + + $row = $this->DB->getRow($query,array( /* 1 */ $argu['user_id'], /* 2 */ $pwd),DB_FETCHMODE_ASSOC); + + if (DB::isError($row)) { + debug($row);exit; + return; + }else{ + return $row; + } + } + + /***** + * 세션에 저장된 상태를 반환한다. + *****/ + function get_status(){ + return array_filter(array( + 'user_no' => $_SESSION['user_no'], + 'user_id' => $_SESSION['user_id'], + 'user_name' => $_SESSION['user_name'], + 'user_level' => $_SESSION['user_level'] + ),'delete_null_array'); + + } + + /***** + * 회원 내용을 반환한다. + *****/ + function get_user_view($user_no){ + $query = " + select + * + from + ".TABLE_USER." + where + user_no = '{$user_no}' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + debug($res); + return; + } + + $row = $res->fetchRow(DB_FETCHMODE_ASSOC); + + return $row; + } + + function get_total(){ + $query = "select found_rows()"; + $total = $this->DB->getOne($query); + + if (DB::isError($total)) { + die($total->getMessage()); + } + return $total; + } + + /***** + * 로그인 상태가 될수 있도록 세션을 생성한다. + *****/ + function set_login_session($data){ + $_SESSION['user_no'] = $data['user_no']; + $_SESSION['user_id'] = $data['user_id']; + $_SESSION['user_name'] = $data['user_name']; + $_SESSION['user_level'] = $data['user_level']; + } + + /***** + * 로그인 정보를 업데이트한다. + *****/ + function set_login_update($data){ + $query=" + update + ".TABLE_USER." + set + user_cnt=user_cnt+1, + user_lastlogin=now() + where + user_no='".$data['user_no']."'"; + + $result = $this->DB->query($query); + + if (DB::isError($result)) { + //debug($this->DB); + die($result->getMessage()); + } + } + + /***** + * 회원을 등록한다. + *****/ + function set_user_insert($argu){ + + global $_adminpage; + global $_lan_alert; + + // 변수 설정 + $argu["user_hp"]=$argu["user_hp1"]."-".$argu["user_hp2"]."-".$argu["user_hp3"]; + $argu["user_level"]=($_adminpage) ? $argu["user_level"] : $this->user_basic_level; + $argu["user_id"]=($_adminpage) ? $argu["user_id"] : $argu["user_email"]; + + $argu['return_url'] = ($argu['return_url']) ? urldecode($argu['return_url']) : ""; + + // 아이디 중복 체크 + $id_chk=$this->check_dupleid($argu["user_id"]); + + if($id_chk['code'] == "D"){ + go_url("","이미 가입된 아이디입니다."); + exit; + }else{ + + /// 빠진 사항 체크 + if(strlen($argu["user_id"])<4){ go_url("","아이디를 입력하지 않으셨거나 형식에 맞지 않습니다."); exit; } + if(strlen($argu["user_pwd"])<4){ go_url("","비밀번호를 입력하지 않으셨거나 형식에 맞지 않습니다."); exit; } + if(strlen($argu["user_name"])<2){ go_url("","성명이 입력되지 않았습니다."); exit; } + + $data = array( + "user_id" => $argu["user_id"], + "user_name" => $argu["user_name"], + "user_hp" => $argu["user_hp"], + "user_email" => $argu["user_email"], + "user_emaillist" => $argu["user_emaillist"], + "user_level" => $argu["user_level"], + "user_memo" => $argu["user_memo"], + "user_withdrawal" => "N", + "user_withdrawal_date" => null, + "user_withdrawal_case" => null, + "user_withdrawal_memo" => null, + "user_ip" => $_SERVER["REMOTE_ADDR"], + "user_regdate" => _NowTime, + "user_cnt" => 0, + "user_lastlogin" => null, + ); + + // 패스워드 암호화 + if(strlen($argu["user_pwd"])>3){ + $pwd1=substr(md5($argu["user_pwd"]),0,20); + $pwd2=substr(md5($argu["user_pwd"]),-20); + + $pwd=$pwd1.$pwd2; + } + + $data = array_merge($data, array("user_pwd" => $pwd)); + + $sth = $this->DB->autoPrepare(TABLE_USER, array_keys($data), DB_AUTOQUERY_INSERT); + $res = $this->DB->execute($sth, array_values($data)); + + if (DB::isError($res)) { + go_url("","회원 등록이 되지 않았습니다.\\n[".$res->getMessage()."]"); + exit; + } + } + + return $argu['return_url']; + } + + /***** + * 회원 리스트를 반환한다. + *****/ + function get_user_list($argu,&$total,$limit = true){ + + /// 검색 쿼리 + $addwhere = "(1=1)"; + if(strlen($argu['keyword']>0)){ $addwhere .= " and {$argu['s_type']} like '%{$argu['keyword']}%' "; } + + $query = " + select + count(*) + from + ".TABLE_USER." + where + $addwhere + "; + + $total = $this->DB->getOne($query); + if (DB::isError($list)) { + die($list->getMessage()); + } + + $query = " + select + * + from + ".TABLE_USER." + where + $addwhere + order by + user_regdate desc "; + if($limit) + $query .= " + limit ".($argu['p']-1)*$this->_LIST_NUM.",".$this->_LIST_NUM; + + $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($list)) { + //debug($this->DB); + die($list->getMessage()); + } + + return $list; + } + + /***** + * 회원 내용을 Update 한다. + * 회원 탈퇴도 Level 만 탈퇴 등급으로 조정하는것으로 처리 하므로 Update Function 에서 처리한다. + *****/ + function set_user_update($argu){ + + global $_adminpage; + + if($argu["mode"]=="DELETE_ACTION"){ + if($_SESSION['user_level']==1){ + $argu["user_withdrawal_case"]="관리자 탈퇴 처리"; + $argu["user_withdrawal_memo"]="관리자 탈퇴 처리"; + } + + $data = array( + "user_level" => $this->user_withdrawal_level, + "user_withdrawal" => "Y", + "user_withdrawal_date" => _NowTime, + "user_withdrawal_case" => $argu["user_withdrawal_case"], + "user_withdrawal_memo" => $argu["user_withdrawal_memo"] + ); + }else{ + + // 변수 설정 + $argu["user_hp"]=$argu["user_hp1"]."-".$argu["user_hp2"]."-".$argu["user_hp3"]; + + $argu["user_level"]=($_adminpage) ? $argu["user_level"] : $this->user_basic_level; + + $data = array( + "user_name" => $argu["user_name"], + "user_hp" => $argu["user_hp"], + "user_email" => $argu["user_email"], + "user_emaillist" => $argu["user_emaillist"], + ); + + if($_adminpage){ + $data=array_merge($data, array( + "user_level" => $argu["user_level"], + "user_memo" => $argu["user_memo"] + )); + + if($argu["user_level"]<$this->user_withdrawal_level){ + $data=array_merge($data, array( + "user_withdrawal" => "N", + "user_withdrawal_date" => null, + "user_withdrawal_case" => null, + "user_withdrawal_memo" => null + )); + } + } + + // 비밀번호를 입력할 경우 비밀번호를 같이 변경한다. + if(strlen($argu["user_pwd"])>3){ + $pwd1=substr(md5($argu["user_pwd"]),0,20); + $pwd2=substr(md5($argu["user_pwd"]),-20); + + $pwd=$pwd1.$pwd2; + + $data=array_merge($data, array( + "user_pwd" => $pwd + )); + } + } + + $result = $this->DB->autoExecute(TABLE_USER, $data, DB_AUTOQUERY_UPDATE, "user_no = '{$argu['user_no']}' "); + + if (DB::isError($result)) { + //debug($this->DB); + die($result->getMessage()); + } + + return true; + } + + function check_login_du($argu){ + $pwd1=substr(md5($argu["du_pwd"]),0,20); + $pwd2=substr(md5($argu["du_pwd"]),-20); + + $pwd=$pwd1.$pwd2; + + $query = " + select + u.du_no, + u.du_email, + u.du_name, + u.du_app + from + ".TABLE_DU_USER." u + where + u.du_email = '".$argu['du_email']."' + and u.du_pwd = '".$pwd."' + "; + + $row = $this->DB->getRow($query,array(),DB_FETCHMODE_ASSOC); + + if (DB::isError($row)) { + debug($row);exit; + return; + }else{ + return $row; + } + } + + + function check_dupleid_du($str){ + if($this->DB->getOne("select count(*) from ".TABLE_DU_USER." where du_email = '{$str}'") > 0){ // 중복 아이디일 경우 + return array("code" => "D","du_email" => $str); + }else{ // 중복 아이디가 아닐경우 + return array("code" => "A","du_email" => $str); + } + } + + function set_login_session_du($data){ + $_SESSION['duser_no'] = $data['du_no']; + $_SESSION['duser_id'] = $data['du_email']; + $_SESSION['duser_name'] = $data['du_name']; + //$_SESSION['du_app'] = $data['du_app']; + } + + + /***** + * 세션에 저장된 상태를 반환한다. + *****/ + function get_status_du(){ + return array_filter(array( + 'duser_no' => $_SESSION['duser_no'], + 'duser_id' => $_SESSION['duser_id'], + 'duser_name' => $_SESSION['duser_name'], + ),'delete_null_array'); + + } + + + function set_du_user_insert($argu){ + + // 아이디 중복 체크 + $du_id_chk=$this->check_dupleid_du($argu["du_email"]); + + if($du_id_chk['code'] == "D"){ + go_url("","This email is already subscribed."); + exit; + }else{ + + $data = array( + "du_name" => $argu["du_name"], + "du_company" => $argu["du_company"], + "du_email" => $argu["du_email"], + "du_region" => $argu["du_region"], + "du_phone_num" => $argu["du_phone_num"], + "du_app" => 'N', + "du_regdate" => _NowTime, + ); + + // 패스워드 암호화 + if(strlen($argu["du_pwd"])>3){ + $pwd1=substr(md5($argu["du_pwd"]),0,20); + $pwd2=substr(md5($argu["du_pwd"]),-20); + + $pwd=$pwd1.$pwd2; + } + + $data = array_merge($data, array("du_pwd" => $pwd)); + + $sth = $this->DB->autoPrepare(TABLE_DU_USER, array_keys($data), DB_AUTOQUERY_INSERT); + $res = $this->DB->execute($sth, array_values($data)); + + if (DB::isError($res)) { + go_url("","Has not been registered.\\n[".$res->getMessage()."]"); + exit; + } + } + + return true; + + } + + function set_du_user_update($argu){ + + $data = array( + "du_name" => $argu["du_name"], + "du_company" => $argu["du_company"], + "du_region" => $argu["du_region"], + "du_phone_num" => $argu["du_phone_num"], + "du_app" => $argu["du_app"], + ); + + + // 비밀번호를 입력할 경우 비밀번호를 같이 변경한다. + if(strlen($argu["du_pwd"])>3){ + $pwd1=substr(md5($argu["du_pwd"]),0,20); + $pwd2=substr(md5($argu["du_pwd"]),-20); + + $pwd=$pwd1.$pwd2; + + $data=array_merge($data, array( + "du_pwd" => $pwd + )); + } + + $result = $this->DB->autoExecute(TABLE_DU_USER, $data, DB_AUTOQUERY_UPDATE, "du_no = '{$argu['du_no']}' "); + + if (DB::isError($result)) { + //debug($this->DB); + die($result->getMessage()); + } + + return true; + + } + + + function set_du_userpwd_update($argu){ + + // 패스워드 암호화 + if(strlen($argu["new_pwd"])>3){ + $pwd1=substr(md5($argu["new_pwd"]),0,20); + $pwd2=substr(md5($argu["new_pwd"]),-20); + + $pwd=$pwd1.$pwd2; + } + + $data = array( + "du_pwd" => $pwd, + ); + + $result = $this->DB->autoExecute(TABLE_DU_USER, $data, DB_AUTOQUERY_UPDATE, "du_no = '{$argu['du_no']}' "); + + if (DB::isError($result)) { + //debug($this->DB); + die($result->getMessage()); + } + + return true; + + } + + + + function set_du_user_delete($du_no){ + $query = "DELETE FROM ".TABLE_DU_USER." WHERE du_no = '".$du_no."'"; + + $res = $this->DB->query($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return true; + + } + + function get_du_user_list($argu,&$total,$limit = true){ + /// 검색 쿼리 + $addwhere = "(1=1)"; + if(strlen($argu['keyword']>0)){ $addwhere .= " and {$argu['s_type']} like '%{$argu['keyword']}%' "; } + + $query = " + select + count(*) + from + ".TABLE_DU_USER." + where + $addwhere + "; + + $total = $this->DB->getOne($query); + if (DB::isError($list)) { + die($list->getMessage()); + } + + $query = " + select + * + from + ".TABLE_DU_USER." + where + $addwhere + order by + du_regdate desc "; + if($limit) + $query .= " + limit ".($argu['p']-1)*$this->_LIST_NUM.",".$this->_LIST_NUM; + + $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($list)) { + //debug($this->DB); + die($list->getMessage()); + } + + return $list; + + } + + function get_du_user_view($du_no){ + $query = " + select + * + from + ".TABLE_DU_USER." + where + du_no = '{$du_no}' + "; + $res = $this->DB->query($query); + if (DB::isError($res)) { + debug($res); + return; + } + + $row = $res->fetchRow(DB_FETCHMODE_ASSOC); + + return $row; + } + + function get_du_id_search($argu){ + // 주민/사업자 등록 번호 암호화 + + $addwhere = "(du_email = '{$argu['du_email']}') "; + + $query = " + select + * + from + ".TABLE_DU_USER." + where + $addwhere + "; + + $row = $this->DB->getRow($query,DB_FETCHMODE_ASSOC); + if (DB::isError($row)) { + //debug($row); + die($row->getMessage()); + exit; + } + + return $row; + + } + + function get_admlog_list($argu,&$total,$limit = true){ + global $_DB; + + $addwhere = " where (1=1) "; + + /// 검색쿼리 + if($argu['Search']){$addwhere .= " and (view like '%{$argu['Search']}%' or history like '%{$argu['Search']}%') "; } + if($argu['s_date'] && $argu['e_date']){$addwhere .= " and (regdate between '{$argu['s_date']} 00:00:00' and '{$argu['e_date']} 23:59:59') "; } + + $query = " + select + count(*) + from + adm_log + ".$addwhere; + + $res = $total = $this->DB->getOne($query); + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + $query = " + select + * + from + adm_log + ".$addwhere." + order by + regdate desc + "; + if($limit) + $query .= " + limit ".($argu['p']-1)*$this->_LIST_NUM.",".$this->_LIST_NUM; + + //echo "
$query
"; + + $res = $list =& $this->DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + + if (DB::isError($res)) { + go_url("", $res->getMessage()); + exit; + } + + return $list; + } + + } +?> \ No newline at end of file diff --git a/common/lib/lib.util.php b/common/lib/lib.util.php new file mode 100644 index 0000000..a8d71f8 --- /dev/null +++ b/common/lib/lib.util.php @@ -0,0 +1,2366 @@ +\n"; + echo "\n"; + print_r($str); + echo "\n\n"; + echo ""; + return true; + } + return false; +} + +/*---------------------------------------- +pageing function & mysql limit function +-----------------------------------------*/ +function page_index($total,$p=1,$link="",$rownum=20,$scale=10,$prev_section_img = "" ,$next_section_img = "" ,$prev_img = "" ,$next_img = "", $first_img = "", $last_img = "", $outside_using="N") +{ + + //페이지가 없으면 첫페이지 + if(empty($p)) $p = 1; + $orig_page = $p; + + //$total이 없으면 1 + if(empty($total) or $total <= 0){ + $total = 1; + } + + $link = str_replace("&&","&",$link); + if(substr($link,0,1) == "&") $link = substr($link,1); + + //filename 없으면 자기자신 + $filename=$_SERVER['PHP_SELF']; + + $total_page = @ceil( $total / $rownum ) ; + $total_zone = ceil($total_page/$scale); // 총 블럭 수 + $zone = ceil($p/$scale); //현재 블럭 + + $first_page = ($zone -1) * $scale; + $last_page = $zone * $scale; + + if($total_zone <= $zone) { + $last_page = $total_page; + } + + + //img 처리 + if(empty($prev_section_img)) $prev_section_img ="";//"◀"; + else $prev_section_img = " 이전블럭 "; + + if(empty($next_section_img)) $next_section_img ="";//"▶"; + else $next_section_img = " 다음블럭 "; + + if(empty($prev_img)) $prev_img ="◀"; + else $prev_img = " 이전 "; + + if(empty($next_img)) $next_img ="▶"; + else $next_img = " 다음 "; + + if(empty($first_img)) $first_img = "1"; + else $first_img = " "; + + if(empty($last_img)) $last_img = "".$total_page.""; + else $last_img = " "; + + # 처음 페이지 링크 + if ($orig_page > 1) { + $f_first_page = "FIRST"; + } else { + $f_first_page = "FIRST"; + } + + # 마지막 페이지 링크 + if ($orig_page < $total_page) { + $l_last_page = "LAST"; + } else { + $l_last_page = "LAST"; + } + + //이전페이지 링크 + if($orig_page > 1){ + $p = $orig_page - 1 ; + $pre_page ="
  • "; + }else{ + $pre_page = "
  • "; + } + + //다음 페이지 링크 + if($orig_page < $total_page){ + $p = $orig_page + 1 ; + $next_page ="
  • "; + }else{ + $next_page = "
  • "; + } + + //이전블록에 대한 링크 + if($zone > 1){ + $p = $first_page; + $p_zone = ""; + }else{ + $p_zone = ""; + }; + + //다음블록에 대한 링크 + if($zone < $total_zone){ + $p = $last_page + 1; + $n_zone =""; + }else{ + $n_zone = ""; + } + + + //각페이지로 이동 링크 + for($page_link = $first_page+1 ; $page_link <= $last_page; $page_link++){ + if($orig_page == $page_link){ + $this_page .= "
  • $page_link
  • "; + }else{ + $this_page .="
  • $page_link
  • "; + } + //if($page_link < $last_page) $this_page .= "I"; + } + + if ($outside_using == "N") { + //$f_first_page = ""; + //$l_last_page = ""; + } + else { + //$f_first_page = $f_first_page . " ... "; + //$l_last_page = " ... " . $l_last_page; + } + + //$page_index = $f_first_page . $p_zone." ".$pre_page." ".$this_page." ".$next_page." ".$n_zone . $l_last_page; + + $page_index = $pre_page.$this_page.$next_page; + return $page_index; +} + + +function page_index_cate($total,$p=1,$link="",$rownum=20,$scale=10,$prev_section_img = "" ,$next_section_img = "" ,$prev_img = "" ,$next_img = "", $first_img = "", $last_img = "", $outside_using="N") +{ + + //페이지가 없으면 첫페이지 + if(empty($p)) $p = 1; + $orig_page = $p; + + //$total이 없으면 1 + if(empty($total) or $total <= 0){ + $total = 1; + } + + $link = str_replace("&&","&",$link); + if(substr($link,0,1) == "&") $link = substr($link,1); + + //filename 없으면 자기자신 + $filename=$_SERVER['PHP_SELF']; + + $total_page = @ceil( $total / $rownum ) ; + $total_zone = ceil($total_page/$scale); // 총 블럭 수 + $zone = ceil($p/$scale); //현재 블럭 + + $first_page = ($zone -1) * $scale; + $last_page = $zone * $scale; + + if($total_zone <= $zone) { + $last_page = $total_page; + } + + + //img 처리 + if(empty($prev_section_img)) $prev_section_img ="";//"◀"; + else $prev_section_img = " 이전블럭 "; + + if(empty($next_section_img)) $next_section_img ="";//"▶"; + else $next_section_img = " 다음블럭 "; + + if(empty($prev_img)) $prev_img ="◀"; + else $prev_img = " 이전 "; + + if(empty($next_img)) $next_img ="▶"; + else $next_img = " 다음 "; + + if(empty($first_img)) $first_img = "1"; + else $first_img = " "; + + if(empty($last_img)) $last_img = "".$total_page.""; + else $last_img = " "; + + # 처음 페이지 링크 + if ($orig_page > 1) { + $f_first_page = "FIRST"; + } else { + $f_first_page = "FIRST"; + } + + # 마지막 페이지 링크 + if ($orig_page < $total_page) { + $l_last_page = "LAST"; + } else { + $l_last_page = "LAST"; + } + + + + + //이전페이지 링크 + if($orig_page > 1){ + $p = $orig_page - 1 ; + $pre_page ="
  • Prev
  • "; + }else{ + $pre_page = "
  • Prev
  • "; + } + + //다음 페이지 링크 + if($orig_page < $total_page){ + $p = $orig_page + 1 ; + $next_page ="
  • Next
  • "; + }else{ + $next_page = "
  • Next
  • "; + } + + //이전블록에 대한 링크 + /*if($zone > 1){ + $p = $first_page; + $p_zone = "$prev_section_img"; + }else{ + $p_zone =$prev_section_img; + };*/ + + //다음블록에 대한 링크 + /*if($zone < $total_zone){ + $p = $last_page + 1; + $n_zone ="$next_section_img"; + }else{ + $n_zone =$next_section_img; + }*/ + + + //각페이지로 이동 링크 + for($page_link = $first_page+1 ; $page_link <= $last_page; $page_link++){ + if($orig_page == $page_link){ + $this_page .= "
  • $page_link
  • "; + }else{ + $this_page .="
  • $page_link
  • "; + } + //if($page_link < $last_page) $this_page .= "I"; + } + + if ($outside_using == "N") { + //$f_first_page = ""; + //$l_last_page = ""; + } + else { + //$f_first_page = $f_first_page . " ... "; + //$l_last_page = " ... " . $l_last_page; + } + + //$page_index = $f_first_page . $p_zone." ".$pre_page." ".$this_page." ".$next_page." ".$n_zone . $l_last_page; + + $page_index = $pre_page.$this_page.$next_page; + return $page_index; +} + +function page_index1($total,$p=1,$link="",$rownum=20,$scale=10,$prev_section_img = "" ,$next_section_img = "" ,$prev_img = "" ,$next_img = "", $first_img = "", $last_img = "", $outside_using="N") +{ + + //페이지가 없으면 첫페이지 + if(empty($p)) $p = 1; + $orig_page = $p; + + //$total이 없으면 1 + if(empty($total) or $total <= 0){ + $total = 1; + } + + $link = str_replace("&&","&",$link); + if(substr($link,0,1) == "&") $link = substr($link,1); + + //filename 없으면 자기자신 + $filename=$_SERVER['PHP_SELF']; + + $total_page = @ceil( $total / $rownum ) ; + $total_zone = ceil($total_page/$scale); // 총 블럭 수 + $zone = ceil($p/$scale); //현재 블럭 + + $first_page = ($zone -1) * $scale; + $last_page = $zone * $scale; + + if($total_zone <= $zone) { + $last_page = $total_page; + } + + + # 처음 페이지 링크 + if ($orig_page > 1) { + $f_first_page = "
    FIRST"; + } else { + $f_first_page = "
    FIRST"; + } + + # 마지막 페이지 링크 + if ($orig_page < $total_page) { + $l_last_page = "LAST
    "; + } else { + $l_last_page = "LAST
    "; + } + + + //이전페이지 링크 + if($orig_page > 1){ + $p = $orig_page - 1 ; + $pre_page ="< PREV"; + }else{ + $pre_page = "< PREV"; + } + + //다음 페이지 링크 + if($orig_page < $total_page){ + $p = $orig_page + 1 ; + $next_page ="
    NEXT >"; + }else{ + $next_page = "
    NEXT >"; + } +/* + //이전블록에 대한 링크 + if($zone > 1){ + $p = $first_page; + $p_zone = "$prev_section_img"; + }else{ + $p_zone =$prev_section_img; + }; + + //다음블록에 대한 링크 + if($zone < $total_zone){ + $p = $last_page + 1; + $n_zone ="$next_section_img"; + }else{ + $n_zone =$next_section_img; + } +*/ + //각페이지로 이동 링크 + + $this_page = "
    "; + for($page_link = $first_page+1 ; $page_link <= $last_page; $page_link++){ + if($orig_page == $page_link){ + $this_page .= "$page_link"; + }else{ + $this_page .="$page_link"; + } + //if($page_link < $last_page) $this_page .= "I"; + } + $this_page .= "
    "; + + /*if ($outside_using == "N") { + $f_first_page = ""; + $l_last_page = ""; + } + else { + //$f_first_page = ""; + //$l_last_page = ""; + $f_first_page = $f_first_page; + $l_last_page = $l_last_page; + }*/ + + //$page_index = $f_first_page . $p_zone." ".$pre_page." ".$this_page." ".$next_page." ".$n_zone . $l_last_page; + $page_index = $f_first_page.$pre_page.$this_page.$next_page.$l_last_page; + return $page_index; +} + + + +function page_index_c($b_class,$target,$cate,$total,$p=1,$link="",$rownum=20,$scale=10,$prev_section_img = "" ,$next_section_img = "" ,$prev_img = "" ,$next_img = "", $first_img = "", $last_img = "", $outside_using="N") +{ + + //페이지가 없으면 첫페이지 + if(empty($p)) $p = 1; + $orig_page = $p; + + //$total이 없으면 1 + if(empty($total) or $total <= 0){ + $total = 1; + } + + $link = str_replace("&&","&",$link); + if(substr($link,0,1) == "&") $link = substr($link,1); + + //filename 없으면 자기자신 + $filename=$_SERVER['PHP_SELF']; + + $total_page = @ceil( $total / $rownum ) ; + $total_zone = ceil($total_page/$scale); // 총 블럭 수 + $zone = ceil($p/$scale); //현재 블럭 + + $first_page = ($zone -1) * $scale; + $last_page = $zone * $scale; + + if($total_zone <= $zone) { + $last_page = $total_page; + } + + //img 처리 + /* + if(empty($prev_section_img)) $prev_section_img ="";//"◀"; + else $prev_section_img = " 이전블럭 "; + + if(empty($next_section_img)) $next_section_img ="";//"▶"; + else $next_section_img = " 다음블럭 "; + */ +// if(empty($prev_img)) $prev_img ="◀"; +// else $prev_img = " 이전 "; +// +// if(empty($next_img)) $next_img ="▶"; +// else $next_img = " 다음 "; + + /* + if(empty($first_img)) $first_img = "1"; + else $first_img = " "; + + if(empty($last_img)) $last_img = "".$total_page.""; + else $last_img = " "; +*/ + # 처음 페이지 링크 + //board(bc,bn,md,p) + /* + if ($orig_page > 1) { + //$f_first_page = "{$first_img}"; + $f_first_page = "{$first_img}"; + } else { + $f_first_page = "".$first_img.""; + } + + # 마지막 페이지 링크 + if ($orig_page < $total_page) { + //$l_last_page = "{$last_img}"; + $l_last_page = "{$last_img}"; + } else { + $l_last_page = "".$last_img.""; + } + */ + + + //이전페이지 링크 + + if($orig_page > 1){ + $p = $orig_page - 1 ; + //$pre_page ="$prev_img"; + $pre_page ="
    "; + }else{ + $pre_page = "
    "; + } + + //다음 페이지 링크 + if($orig_page < $total_page){ + $p = $orig_page + 1 ; + //$next_page ="$next_img"; + $next_page ="
    "; + }else{ + $next_page = "
    "; + } +/* + //이전블록에 대한 링크 + if($zone > 1){ + $p = $first_page; + $p_zone = "$prev_section_img"; + }else{ + $p_zone =$prev_section_img; + }; + + //다음블록에 대한 링크 + if($zone < $total_zone){ + $p = $last_page + 1; + $n_zone ="$next_section_img"; + }else{ + $n_zone =$next_section_img; + } +*/ + //각페이지로 이동 링크 +/* + for($page_link = $first_page+1 ; $page_link <= $last_page; $page_link++){ + if($orig_page == $page_link){ + $this_page .= " $page_link "; + }else{ + //$this_page .=" $page_link "; + $this_page .=" $page_link "; + } + if($page_link < $last_page) $this_page .= "I"; + } + + if ($outside_using == "N") { + $f_first_page = ""; + $l_last_page = ""; + } + else { + $f_first_page = $f_first_page . " ... "; + $l_last_page = " ... " . $l_last_page; + } +*/ + $page_index = $pre_page.$next_page; + return $page_index; +} + +function page_index_admin($total,$p=1,$link="",$rownum=20,$scale=10,$prev_section_img = "" ,$next_section_img = "" ,$prev_img = "" ,$next_img = "", $first_img = "", $last_img = "", $outside_using="N") +{ + + //페이지가 없으면 첫페이지 + if(empty($p)) $p = 1; + $orig_page = $p; + + //$total이 없으면 1 + if(empty($total) or $total <= 0){ + $total = 1; + } + + $link = str_replace("&&","&",$link); + if(substr($link,0,1) == "&") $link = substr($link,1); + + //filename 없으면 자기자신 + $filename=$_SERVER['PHP_SELF']; + + $total_page = @ceil( $total / $rownum ) ; + $total_zone = ceil($total_page/$scale); // 총 블럭 수 + $zone = ceil($p/$scale); //현재 블럭 + + $first_page = ($zone -1) * $scale; + $last_page = $zone * $scale; + + if($total_zone <= $zone) { + $last_page = $total_page; + } + + //이전페이지 링크 + if($orig_page > 1){ + $p = $orig_page - 1 ; + $pre_page ="
  • Previous
  • "; + }else{ + $pre_page = "
  • Previous
  • "; + } + + //다음 페이지 링크 + if($orig_page < $total_page){ + $p = $orig_page + 1 ; + $next_page ="
  • Next
  • "; + }else{ + $next_page = "
  • Next
  • "; + } + + + //각페이지로 이동 링크 + for($page_link = $first_page+1 ; $page_link <= $last_page; $page_link++){ + if($orig_page == $page_link){ + $this_page .= "
  • $page_link
  • "; + }else{ + $this_page .="
  • $page_link
  • "; + } + } + + $page_index = $pre_page.$this_page.$next_page; + return $page_index; +} + + +if (phpversion () < "5"){ // define PHP5 functions if server uses PHP4 + function str_split($text, $split = 1){ + if (!is_string($text)) return false; + if (!is_numeric($split) && $split < 1) return false; + $len = strlen($text); + $array = array(); + $s = 0; + $e=$split; + while ($s <$len){ + $e=($e <$len)?$e:$len; + $array[] = substr($text, $s,$e); + $s = $s+$e; + } + return $array; + } +} + +/*------------------------------------------------------ +한글 문자열 자르기 , 유니 코드 포함 +$isUni = true 이면 유니코드문자열 처리 +-------------------------------------------------------*/ +##TODO : 유니코드를 자동으로 인식할수 없을까? +function ksubstr___($str, $limitLen,$suffix="...",$isUni = true) +{ + $strLen = strlen( $str ); + + //제한 문자길이 보다 작다면 그대로 리턴 + if ( $limitLen > $strLen ){ + return $str; + } + $str = substr( $str, 0, $limitLen ); + + $kChar = 0; + for( $i = $limitLen -1 ; $i >= 0 ;$i-- ){ + $lastChar = ord($str[$i]); + if($lastChar < 127){ + break; //정상적인 영문자,숫자라면..stop + } else{ + $kChar++; //한글이나 특수 문작 + } + + }//for + + //한문자 길이 + ($isUni) ? $divide = 3 : $divide = 2 ; + + //문자가 깨지지않게 맞추기 + if($rest = $kChar % $divide > 0){ + $str = substr($str,0,$limitLen - $rest); + } + + return $str.$suffix; +} + + +function ksubstr($str, $len, $checkmb=false, $tail='...') { + /** + * UTF-8 Format + * 0xxxxxxx = ASCII, 110xxxxx 10xxxxxx or 1110xxxx 10xxxxxx 10xxxxxx + * latin, greek, cyrillic, coptic, armenian, hebrew, arab characters consist of 2bytes + * BMP(Basic Mulitilingual Plane) including Hangul, Japanese consist of 3bytes + **/ + preg_match_all('/[\xE0-\xFF][\x80-\xFF]{2}|./', $str, $match); // target for BMP + + $m = $match[0]; + $slen = strlen($str); // length of source string + $tlen = strlen($tail); // length of tail string + $mlen = count($m); // length of matched characters + + if ($slen <= $len) return $str; + if (!$checkmb && $mlen <= $len) return $str; + + $ret = array(); + $count = 0; + for ($i=0; $i < $len; $i++) { + $count += ($checkmb && strlen($m[$i]) > 1)?2:1; + if ($count + $tlen > $len) break; + $ret[] = $m[$i]; + } + + return join('', $ret).$tail; +} + +function strcut_utf8($str, $len, $checkmb=false, $tail='...') { + /** + * UTF-8 Format + * 0xxxxxxx = ASCII, 110xxxxx 10xxxxxx or 1110xxxx 10xxxxxx 10xxxxxx + * latin, greek, cyrillic, coptic, armenian, hebrew, arab characters consist of 2bytes + * BMP(Basic Mulitilingual Plane) including Hangul, Japanese consist of 3bytes + **/ + preg_match_all('/[\xE0-\xFF][\x80-\xFF]{2}|./', $str, $match); // target for BMP + + $m = $match[0]; + $slen = strlen($str); // length of source string + $tlen = strlen($tail); // length of tail string + $mlen = count($m); // length of matched characters + + if ($slen <= $len) return $str; + if (!$checkmb && $mlen <= $len) return $str; + + $ret = array(); + $count = 0; + for ($i=0; $i < $len; $i++) { + $count += ($checkmb && strlen($m[$i]) > 1)?2:1; + if ($count + $tlen > $len) break; + $ret[] = $m[$i]; + } + + return join('', $ret).$tail; +} + + /***** + * 파일 다운로드 + * $fullpath : 물리적 파일이름까지 포함한 전체 경로 + * $filename : 다운로드시 저장될 파일 이름 + *****/ + function download($fullpath, $filename){ + $HTTP_USER_AGENT = $_SERVER["HTTP_USER_AGENT"]; + //global $HTTP_USER_AGENT; + $filename = urlencode($filename); + if(eregi("(MSIE 5.0|MSIE 5.1|MSIE 5.5|MSIE 6.0|MSIE 7.0|MSIE 8.0|MSIE 9.0)", $HTTP_USER_AGENT)){ + if(strstr($HTTP_USER_AGENT, "MSIE 5.5")){ + header("Content-Type: doesn/matter"); + header("Content-disposition: filename=\"$filename\""); + header("Content-Transfer-Encoding: binary"); + header("Pragma: no-cache"); + header("Expires: 0"); + } + + if(strstr($HTTP_USER_AGENT, "MSIE 5.0")){ + Header("Content-type: file/unknown"); + header("Content-Disposition: attachment; filename=\"$filename\""); + Header("Content-Description: PHP3 Generated Data"); + header("Pragma: no-cache"); + header("Expires: 0"); + } + + if(strstr($HTTP_USER_AGENT, "MSIE 5.1")){ + Header("Content-type: file/unknown"); + header("Content-Disposition: attachment; filename=\"$filename\""); + Header("Content-Description: PHP3 Generated Data"); + header("Pragma: no-cache"); + header("Expires: 0"); + } + + if(strstr($HTTP_USER_AGENT, "MSIE")){ + Header("Content-type: application/x-msdownload"); + Header("Content-Length: ".(string)(filesize("$fullpath"))); + Header("Content-Disposition: attachment; filename=\"$filename\""); + Header("Content-Transfer-Encoding: binary"); + Header("Pragma: no-cache"); + Header("Expires: 0"); + } + }else{ + $filename = urldecode($filename); + Header("Content-type: file/unknown"); + Header("Content-Length: ".(string)(filesize("$fullpath"))); + Header("Content-Disposition: attachment; filename=\"$filename\""); + Header("Content-Description: PHP3 Generated Data"); + Header("Pragma: no-cache"); + Header("Expires: 0"); + } + + if (is_file("$fullpath")){ + $fp = fopen("$fullpath", "rb"); + + if (!fpassthru($fp)) + fclose($fp); + + }else{ + go_url("", "해당 파일이나 경로가 존재하지 않습니다."); + } + } + + + /***** + * 배열의 모든값들에 대해 \문자를 제거한다. + * by sqlplus + *****/ + function StripAllSlashes (&$ArrayGET, $Value){ + if (is_array ($ArrayGET)) array_walk ($ArrayGET, "StripAllSlashes"); + else $ArrayGET = stripslashes ($ArrayGET); + } + + /***** + * 배열의 모든 요소들을 trim 한다 + * by sqlplus + *****/ + function trimvalues (&$ArrayGET, $Value){ + if (is_array ($ArrayGET)) array_walk ($ArrayGET, "trimvalues"); + else $ArrayGET = trim ($ArrayGET); + } + + /***** + * 배열에서 값이 null인것은 제거 시켜준다. + *****/ + function delete_null_array($var){ + return ($var !== null && trim($var) != ""); + } + + /***** + * 배열에서 값이 null인것은 제거 시켜준다. + *****/ + + function remove_null_array($var){ + $newArray = array(); + $nKey=0; + + if(is_array($var)){ + foreach($var as $key => $value){ + if($value !== null && trim($value) != ""){ + $newArray[$nKey] = $value; + $nKey++; + } + } + }else{ + $newArray = $var; + } + + return $newArray; + } + + /***** + * 배열의 모든 요소의 특수 문자를 HTML 엔터티로 변환합니다. + * by sqlplus + *****/ + function htmlspecialcharsAll (&$Array, $Value){ + if (is_array ($Array)) array_walk ($Array, "htmlspecialcharsAll"); + else $Array = htmlspecialchars ($Array,ENT_QUOTES); + } + + function go_url($url = "",$msg = "",$target = "") { + $str = _DOCTYPE." + + + + + "._TITLE." + + + "; + if(trim($msg)!=""){// message가 있을경우 + $str .= " + + "; + } + if(trim($url)!=""){// url 이 있을경우 + if($target){ // 프레임구조에서 타겟이 정해져 있을경우 + $str .= ""; + }else{ + $str .= ""; + //$str .= ""; + } + }else{ + $str .= " + + "; + } + $str .= " + + + "; + define("_ALERT", "1"); + define("_MSG", $str); + exit; + } + + function go_confirm($msg = "",$url = "",$cancel_url = ""){ + $str = _DOCTYPE." + + + + + "._TITLE." + + + "; + + if(trim($cancel_url)!=""){ + $cancel_url = "else{location.replace('".$cancel_url."');}"; + } + + if(trim($msg)!=""){// message가 있을경우 + $str .= " + + "; + } + $str .= " + + + "; + define("_ALERT", "1"); + define("_MSG", $str); + exit; + } + + function close_alert($msg,$url = ""){ + $str = _DOCTYPE." + + + + + "._TITLE." + + + + + + "; + define("_ALERT", "1"); + define("_MSG", $str); + exit; + } + + // by sqlplus + function thumbnail($file, $save_filename, $save_path, $max_width, $max_height,$watermark_file = ""){ + + $x0=10 ; $y0=30 ; + + list($img_width, $img_height, $type, $attr) = getimagesize($file); + /* type + 1 = GIF, 2 = JPG, 3 = PNG, 4 = SWF, + 5 = PSD, 6 = BMP, 7 = TIFF(intel byte order), 8 = TIFF(motorola byte order), + 9 = JPC, 10 = JP2, 11 = JPX, 12 = JB2, + 13 = SWC, 14 = IFF, 15 = WBMP, 16 = XBM + */ + if($type == 1){ + $src_img = ImageCreateFromGif($file); + }elseif($type == 2){ + $src_img = ImageCreateFromJPEG($file); + }elseif($type == 3){ + $src_img = ImageCreateFromPNG($file); + }else{ + return 0; + } + + # 비율 수정 + $ratio = ($img_width/$max_width >= $img_height/$max_height)? $img_width/$max_width:$img_height/$max_height; + $dst_width = $img_width/$ratio; + $dst_height = $img_height/$ratio; + + if($dst_width < $max_width) $srcx = ceil(($max_width - $dst_width)/2); else $srcx = 0; + if($dst_height < $max_height) $srcy = ceil(($max_height - $dst_height)/2); else $srcy = 0; + + if($type == 1){ + $dst_img = imagecreate($max_width, $max_height); + }else{ + $dst_img = imagecreatetruecolor($max_width, $max_height); + } + + $bgc = ImageColorAllocate($dst_img, 255, 255, 255); + ImageFilledRectangle($dst_img, 0, 0, $max_width, $max_height, $bgc); + ImageCopyResampled($dst_img, $src_img, $srcx, $srcy, 0, 0, $dst_width, $dst_height, ImageSX($src_img),ImageSY($src_img)); + + if($type == 1){ + ImageInterlace($dst_img); + ImageGif($dst_img, $save_path."/".$save_filename); + }elseif($type == 2){ + ImageInterlace($dst_img); + ImageJPEG($dst_img, $save_path."/".$save_filename); + }elseif($type == 3){ + ImagePNG($dst_img, $save_path."/".$save_filename); + } + chmod($save_path."/".$save_filename,0644); + ImageDestroy($dst_img); + ImageDestroy($src_img); + + } + + + # 처리시간 처리를 위해 추가 + function microtime_float() + { + list($usec, $sec) = explode(" ", microtime()); + return ((float)$usec + (float)$sec); + } + + function calendar($year,$month){ + $last_day = 31-((($month-(($month<8)? 1:0))%2)+(($month==2)?((!($year%((!($year%100))? 400 :4)))? 1:2):0)); + + for($w = 0;$w < 6;$w++){ + for($d=0;$d<7;$d++){ + $day = ($w==0)? ( (date("w", strtotime($year.'-'.$month.'-1')) <= $d)? $day + 1:0 ):( $day + 1 ); + $calendar[$w][chr(65+$d)] = ($day > $last_day)? 0:$day; + } + if($day >= $last_day) break; + } + return $calendar; + } + + function check_day($year,$month,$day){ + return strtotime(date('Y-m-d')) - strtotime($year.'-'.$month.'-'.$day); + } + + /***** + * 첨부파일 업로드 + * $tag : U upload, D delete + *****/ + function upload($path,$OBJ_FILES,$filename,$tag = "U"){ + $arr_path = split("/",$path); + if($tag == "U"){ // 파일 업로드일 경우 + // 확장자 체크 + if(preg_match('/\\.(php|htm|html|asp|jsp|js|com|bat)$/i', strtolower($OBJ_FILES['name']))){ // 확장자 금지항목 체크 + go_url("","금지된 확장자의 파일 업로드를 시도하셨습니다."); + } + + // 저장할 디렉토리가 존재하지 않으면 생성한다. + for($i=1;$i 0 ){// 첨부파일이 있을경우 + // 확장자 체크 + if(preg_match('/\\.(php|htm|html|asp|jsp|js|com|bat)$/i', strtolower($OBJ_FILES['name']))){ // 확장자 금지항목 체크 + go_url("","금지된 확장자의 파일 업로드를 시도하셨습니다."); + exit; + } + + // 저장할 디렉토리가 존재하지 않으면 생성한다. + for($i=1;$i"; + } + + function get_input_code($type,$code,$name,$value="",$class="text_03",$script=""){ + global $_CODE; + $items = $_CODE[$code]; + $str = ""; + switch($type){ + case "select": + $str .= "\n"; + break; + case "select2": + $str .= "\n"; + break; + case "radio": + foreach( $items as $key => $val ){ + $checked = ($key==$value)? " checked":""; + $str .= " {$val} \n"; + } + break; + case "radio2": + $checked = (!$value)? " checked":""; + $str .= " 전체 "; + foreach( $items as $key => $val ){ + $checked = ($key==$value)? " checked":""; + $str .= " {$val} "; + } + break; + case "checkbox": + foreach( $items as $key => $val ){ + //$checked = ($key==$value)? " checked":""; + $checked = strstr((string) $value, (string) $key)? " checked":""; + $str .= "{$val} \n"; + } + break; + } + return $str; + } + + function get_view_code($type,$code,$name,$value="",$class="text04"){ + global $_CODE; + $items = $_CODE[$code]; + $str = ""; + switch($type){ + case "select": + $str .= "\n"; + break; + case "radio": + foreach( $items as $key => $val ){ + if(strstr((string) $value, (string) $key)) + $str .= " {$val} \n"; + } + break; + case "checkbox": + foreach( $items as $key => $val ){ + if(strstr((string) $value, (string) $key)) + $str .= "{$val} "; + } + break; + } + return $str; + } + + function get_userName($user_id){ + global $_DB; + if(!$user_id) return; + return $_DB->getOne("select user_name from user where user_id = ? ",$user_id); + } + + function get_userTel($user_id){ + global $_DB; + if(!$user_id) return; + return $_DB->getOne("select user_tel from user where user_id = ? ",$user_id); + } + + function get_userHp($user_id){ + global $_DB; + if(!$user_id) return; + return $_DB->getOne("select user_hp from user where user_id = ? ",$user_id); + } + + + function get_agencyName($a_id){ + global $_DB; + if(!$a_id) return "본사"; + return $_DB->getOne("select a_company from agency where a_id = ? ",$a_id); + } + + function get_imgsize($file,$max_width,$max_height=0){ + if( $file != '' && file_exists($file) ) { + list($img_width, $img_height, $type, $attr) = @getimagesize($file); + + if($type == 1 || $type == 2 || $type == 3){ + # 비율 수정 + if($max_height>0){ + $ratio = ($img_width/$max_width >= $img_height/$max_height) ? $img_width/$max_width:$img_height/$max_height; + + if( $ratio <= 1) $ratio = 1; + $dst_width = round($img_width/$ratio); + $dst_height = round($img_height/$ratio); + + return " width='$dst_width' height='$dst_height' "; + }else{ + $ratio = $img_width/$max_width; + + if( $ratio <= 1) $ratio = 1; + $dst_width = round($img_width/$ratio); + $dst_height = round($img_height/$ratio); + + return " width='$dst_width' height='$dst_height' "; + } + }else{ + return; + } + }else{ + return; + } + } + + class SelectHanCategory + { + /* + ㄱ : ㄱ + ㄴ : ㄴ + ㄷ : ㄷ + ㄹ : ㄹ + ㅁ : ㅁ + ㅂ : ㅂ + ㅅ : ㅅ + ㅇ : ㅇ + ㅈ : ㅈ + ㅊ : ㅊ + ㅋ : ㅋ + ㅌ : ㅌ + ㅍ : ㅍ + ㅎ : ㅎ + */ + // 가..나..다..의 16진수값들 + var $hexcode = array("0088" => "A", "b0a1" => "ㄱ", "b3aa" => "ㄴ","b4d9" => "ㄷ", "b6f3" => "ㄹ","b8b6" => "ㅁ", + "b9d9" => "ㅂ","bbe7" => "ㅅ", "bec6" => "ㅇ","c0da" => "ㅈ", "c2f7" => "ㅊ", + "c4ab" => "ㅋ", "c5b8" => "ㅌ", "c6c4" => "ㅍ","c7cf" => "ㅎ", "c8ff" => ""); + var $hexarray, $hexcount; + + function SelectHanCategory() { + $this->hexcount = count($this->hexcode); + for($i=0; $i < $this->hexcount ; $i++) { + $this->hexarray[] = key($this->hexcode); + next($this->hexcode); + } + } + + function IsHangul($ch) { + $ch = ord($ch); + if($ch >= 0xa1 && $ch <= 0xfe) return true; + return false; + } + + function Check($str) { + if($this->IsHangul(substr($str, 0, 1))) { + $current_hexcode = bin2hex(substr($str, 0, 2)); + for ($i=0,$j=1;$i<$this->hexcount;$i++,$j++) { + if ($current_hexcode>=$this->hexarray[$i] && $current_hexcode<$this->hexarray[$j]) { + break; + } + } + return array($j,$this->hexcode[$this->hexarray[$i]]); + }else{ + return array( strtoupper(substr($str, 0, 1)) , strtoupper(substr($str, 0, 1)) ); + } + //} return array(-1); + } + } + //$category = new SelectHanCategory(); + //$return = $category->Check("a파하하하.. 안녕하세요."); + //echo "해당 카테고리 : $return[1] , DB에 저장한 값 : $return[0]"; + + + + // 메시지발송 SendMesg(보내는 사람 연락처, 메시지, 전송완료알림창 ( 1:띄움, 0:안띄움 ), 받는 사람 연락처) + function SendMesg($hpSender, $hpMesg, $endAlert, $hpReceiver=_SMS_HP) { + $userid = _SMS_ID; // 문자나라 아이디 + $passwd = _SMS_PW; // 문자나라 비밀번호 + $adminPhone = _SMS_HP; // 비상시 메시지를 받으실 관리자 핸드폰번호 + + /* UTF-8 글자셋 일 경우 */ + $hpMesg = iconv("UTF-8", "EUC-KR", $hpMesg); + + $hpMesg = urlencode($hpMesg); + + $url = "/MSG/send/web_admin_send.htm?userid=".$userid."&passwd=".$passwd."&sender=".$hpSender."&receiver=".$hpReceiver."&encode=1&end_alert=".$endAlert."&message=".$hpMesg; + + $fp = fsockopen("211.233.20.184", 80, $errno, $errstr, 10); + + if(!$fp) echo "$errno : $errstr"; + + fwrite($fp, "GET $url HTTP/1.0\r\nHost: 211.233.20.184\r\n\r\n"); + $flag = 0; + + while(!feof($fp)){ + $row = fgets($fp, 1024); + + if($flag) $out .= $row; + + if($row=="\r\n") $flag = 1; + } + + fclose($fp); + + return iconv("EUC-KR", "UTF-8", $out); + } + + function get_banner($pos,$cat){ + global $_DB; + if(!$pos) return; + if(!$cat) return; + + $query = " + select + * + from + banner + where + b_pos = ? + and b_cat = ? + limit 1 + "; + $_row = $_DB->getRow($query,array($pos,$cat),DB_FETCHMODE_ASSOC); + + if (DB::isError($_row)) { + //print_r($row); + die($_row->getMessage()); + } + + if(file_exists(_PDS."banner/{$_row['b_no']}") && $_row['b_file']){ + $str = ""; + if($_row['b_link']) $str .= ""; + $str .= ""; + if($_row['b_link']) $str .= ""; + + return $str; + }else{ + return; + } + } + + function get_nav($c_id){ + global $_DB,$_basic,$_PRODUCT_TYPE; + $str = ""; + $separator = " > "; + $len = strlen($c_id); + if($len){ + $str .= $_PRODUCT_TYPE[$c_id[0]]; + for( $i = 1 ; $i <= floor( ( $len - 1 ) / 3 ) ; $i++ ){ + $res = $c_name = $_DB->getOne(" select c_name from category where c_id = ? ",substr($c_id,0,1+(3*($i)))); + if (DB::isError($res)) { + //debug($res); + die($res->getMessage()); + } + $str .= $separator; + $str .= $c_name; + } + } + return $str; + } + + function get_goods_swfnum($c_id){ + global $_PRODUCT_TYPE; + if($_PRODUCT_TYPE[$c_id[0]]){ + switch($c_id[0]){ + case "A":return 1;break; + case "B":return 2;break; + case "C":return 3;break; + case "D":return 4;break; + case "E":return 5;break; + case "F":return 6;break; + case "G":return 7;break; + case "H":return 8;break; + case "I":return 9;break; + } + }else return ""; + } + + function get_category_list($c_type){ + global $_DB; + + $query = " + select + * + from + category c + where + c_num1 > 0 + and c_type = '{$c_type}' + order by + c_id asc + "; + $res = $_list =& $_DB->getAll($query, array(), DB_FETCHMODE_ASSOC); + if (DB::isError($res)) { + debug($query); + die($res->getMessage()); + } + + return $_list; + } + + function ext_get($value){ + return strtolower(array_pop(explode('.',$value))); + } + + + function replace_icon($str){ + for( $fs = 1 ; $fs <= 19 ; $fs++ ){ + $str = str_replace('{'.$fs.'}',"",$str); + } + return $str; + } + + function removeTags($text){ + $text = preg_replace("/(\)/si", "dada", "$text"); + $text = strip_tags($text); + $text = str_replace(" + + + +PNG transparency problem in Internet Explorer'; +$only_gd = '
    (only works with GD (any version), this server is '.($ServerInfo['gd_string'] ? 'running GD "'.$ServerInfo['gd_string'].'" so it will' : 'not running any recognized version of GD so it will not').' work)'; +$only_gd2 = '
    (only works with GD v2.0+, this server is running GD "'.($ServerInfo['gd_string'] ? $ServerInfo['gd_string'] : 'n/a').'" so it '.(($ServerInfo['gd_numeric'] >= 2) ? 'will' : 'will not').' work)'; +$only_php42 = '
    (only works with PHP v4.2.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.2.0', '>=') ? 'will' : 'will not').' work)'; +$only_php43 = '
    (only works with PHP v4.3.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.3.0', '>=') ? 'will' : 'will not').' work)'; +$only_php432 = '
    (only works with PHP v4.3.2+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '4.3.2', '>=') ? 'will' : 'will not').' work (correctly))'; +$only_php500 = '
    (only works with PHP v5.0.0+, this server is running PHP v'.phpversion().' so it '.(version_compare(phpversion(), '5.0.0', '>=') ? 'will' : 'will not').' work (correctly))'; +$php5_or_IM = '
    (only works with PHP v5.0.0+ or ImageMagick, this server is running PHP v'.phpversion().' and "'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a').'" so it '.(($ServerInfo['im_version'] && version_compare(phpversion(), '5.0.0', '>=')) ? 'will' : 'will not').' work (correctly))'; +$only_exif = '
    (only works when the EXIF extension is loaded, so on this server it '.(extension_loaded('exif') ? 'will' : 'will not').' work)'; +$only_im = '
    (requires ImageMagick, this server is running "'.($ServerInfo['im_version'] ? $ServerInfo['im_version'] : 'n/a').'" so it '.($ServerInfo['im_version'] ? 'will' : 'will not').' work)'; + +$Examples[] = array('getstrings' => array($phpThumbBase), 'description' => 'phpThumb version'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['square'].'&w=200'), 'description' => 'width=200px'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['square'].'&w=200&q=10&sia=custom-filename'), 'description' => 'width=200px, JPEGquality=10%, SaveImageAs=custom-filename'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['watermark'].'&w=400&aoe=1&bg=ffffff'), 'description' => 'width=400px, AllowOutputEnlargement enabled'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['square'].'&w=250&sx=600&sy=5&sw=100&sh=100&aoe=1'), 'description' => 'section from (600x5 - 700x105) cropped and enlarged by 250%, AllowOutputEnlargement enabled'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.urlencode('http://silisoftware.com/images/SiliSoft.gif').'&w=100'), 'description' => 'HTTP source image'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['square'].'&w=200&fltr[]=wmi|'.$img['watermark'].'|BL'), 'description' => 'width=200px, watermark (bottom-left, 75% opacity)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['square'].'&w=200&fltr[]=wmi|'.$img['watermark'].'|*|25'), 'description' => 'width=200px, watermark (tiled, 25% opacity)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['watermark'].'&bg=00FFFF&f=png', $phpThumbBase.'?src='.$img['watermark'].'&bg=00FFFF&f=gif', $phpThumbBase.'?src='.$img['watermark'].'&bg=00FFFF&f=jpeg'), 'description' => 'source image (GIF) transpancy with transparent output (PNG, GIF) vs. specified background color (JPEG)'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['anigif'], $phpThumbBase.'?src='.$img['anigif'].'&w=25&f=gif', $phpThumbBase.'?src='.$img['anigif'].'&w=25&f=png', $phpThumbBase.'?src='.$img['anigif'].'&w=25&f=ico', $phpThumbBase.'?src='.$img['anigif'].'&w=25&f=bmp', $phpThumbBase.'?src='.$img['anigif'].'&w=25&f=jpeg'), 'description' => 'resize animated GIF. Notice how output format affects the result: GIF is animated and transparent; PNG and ICO are tranparent but not animated (first frame is rendered as a still image); JPEG and BMP are neither transparent nor animated. Any filters will disable animated resizing (may be fixed in a future version).
    '.$only_im); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['anigif'], $phpThumbBase.'?src='.$img['anigif'].'&sfn=0&f=png', $phpThumbBase.'?src='.$img['anigif'].'&sfn=2&f=png'), 'description' => 'Specifying still-image source frame in multi-frame source images
    '.$only_im); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['alpha'].'&f=png', $phpThumbBase.'?src='.$img['alpha'].'&f=ico', $phpThumbBase.'?src='.$img['alpha'].'&f=gif', $phpThumbBase.'?src='.$img['alpha'].'&f=jpeg'), 'description' => 'PNG alpha transparency test, using test image from the PNG transparency test page'.$only_php432); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=usm|80|0.5|3'), 'description' => 'normal vs. unsharp masking at default settings'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=blur|1', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=blur|5'), 'description' => 'normal vs. blur at default (1) and heavy (5)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=gblr', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=sblr'), 'description' => 'normal vs. gaussian blur vs. selective blur'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['portrait'].'&w=100&h=100&far=L&bg=0000FF&f=png&fltr[]=bord|1', $phpThumbBase.'?src='.$img['landscape'].'&w=100&h=100&far=T&bg=FF0000&f=png&fltr[]=bord|1', $phpThumbBase.'?src='.$img['portrait'].'&w=100&h=100&far=C&bg=0000FF&f=png&fltr[]=bord|1', $phpThumbBase.'?src='.$img['landscape'].'&w=100&h=100&far=B&bg=FF0000&f=png&fltr[]=bord|1', $phpThumbBase.'?src='.$img['portrait'].'&w=100&h=100&far=R&bg=0000FF&f=png&fltr[]=bord|1'), 'description' => 'Forced Aspect Ratio, colored background, PNG output'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['portrait'].'&w=150&ar=L', $phpThumbBase.'?src='.$img['landscape'].'&w=150&ar=L'), 'description' => 'auto-rotate counter-clockwise to landscape from portrait & lanscape'.$only_php42.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['portrait'].'&hp=100&wl=200', $phpThumbBase.'?src='.$img['landscape'].'&hp=100&wl=200'), 'description' => 'auto-selection of W and H based on source image orientation'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['unrotated'].'&w=150&h=150', $phpThumbBase.'?src='.$img['unrotated'].'&w=150&h=150&ar=x'), 'description' => 'original image vs. auto-rotated based on EXIF data'.$only_php42.$only_exif.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&ra=30&bg=0000FF', $phpThumbBase.'?src='.$img['landscape'].'&w=200&ra=30&f=png', $phpThumbBase.'?src='.$img['alpha'].'&ra=30&f=png', $phpThumbBase.'?src='.$img['alpha'].'&ra=30&f=gif'), 'description' => 'Rotated 30 (counter-clockwise), width=200px, blue background vs. transparent background vs. rotated image with pre-existing alpha'.$only_php42.$only_gd); +//$Examples[] = array('getstrings' => array($phpThumbBase.'?src=images/1-bit.gif&ra=30&f=png', $phpThumbBase.'?src=images/4-bit.gif&ra=30&f=png', $phpThumbBase.'?src=images/8-bit.gif&ra=30&f=png'), 'description' => '2-color, 16-color, 256-color transparent GIFs'.$only_php42.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&h=300&far=1&bg=CCCCCC', $phpThumbBase.'?src='.$img['landscape'].'&w=200&h=300&iar=1'), 'description' => 'Normal resize behavior (left) vs. Forced non-proportional resize (right)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=100&h=50&zc=1', $phpThumbBase.'?src='.$img['landscape'].'&w=100&zc=1', $phpThumbBase.'?src='.$img['landscape'].'&h=50&zc=1', $phpThumbBase.'?src='.$img['portrait'].'&w=100&h=50&zc=1', $phpThumbBase.'?src='.$img['portrait'].'&w=100&zc=1', $phpThumbBase.'?src='.$img['portrait'].'&h=50&zc=1'), 'description' => 'Zoom-Crop'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=crop|50', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=crop|0|0|0|0.25'), 'description' => 'crop filter'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=bord|2|20|10|009900&f=png'), 'description' => '2px border, curved border corners (20px horizontal radius, 10px vertical radius)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=ric|50|20&f=png'), 'description' => 'curved border corners (20px vertical radius, 50px horizontal radius)
    '.$png_alpha.$only_gd2.$only_php432); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=sat|75', $phpThumbBase.'?src='.$img['landscape'].'&w=200', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=sat|-100'), 'description' => 'saturation -75% vs. normal vs. -100%'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=ds|75', $phpThumbBase.'?src='.$img['landscape'].'&w=200', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=ds|-100'), 'description' => 'desaturated 75% vs. normal vs. -100%'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=clr|25|00FF00'), 'description' => 'colorized 25% to green (#00FF00)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=gray', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=sep'), 'description' => 'grayscale vs. sepia'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask3'].'&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask1'].'&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask2'].'&f=jpeg&bg=9900CC&q=100'), 'description' => 'Assorted alpha masks (seen below) applied
    '.$png_alpha.$only_php432.'
    JPEG/GIF output is flattened to "bg" background color'.$only_gd2.'
    '); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=drop|5|10|000000|225&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask3'].'&fltr[]=drop|5|10|000000|225&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=drop|5|10|000000|225&fltr[]=elip&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=elip&fltr[]=drop|5|10|000000|225&f=png'), 'description' => 'Drop shadow. Note how the order in which filters are applied matters.'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=elip&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=elip&f=jpeg&bg=00FFFF'), 'description' => 'Elipse
    '.$png_alpha.$only_php432.'
    JPEG/GIF output is flattened to "bg" background color'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=flip|x', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=flip|y', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=flip|xy'), 'description' => 'flipped on X, Y and X+Y axes'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=bvl|10|FFFFFF|000000', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=bvl|10|000000|FFFFFF'), 'description' => '10px bevel edge filter'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=fram|3|2|CCCCCC|FFFFFF|000000', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=fram|3|2|CC9966|333333|CCCCCC'), 'description' => '3+2px frame filter'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=neg'), 'description' => 'Negative filter (inverted color)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=th|105', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=mask|'.$img['mask1'].'&fltr[]=th|105&f=png'), 'description' => 'Threshold filter; showing preserved alpha channel'.$only_php432.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['portrait'].'&w=150', $phpThumbBase.'?src='.$img['portrait'].'&w=150&fltr[]=rcd|16|1', $phpThumbBase.'?src='.$img['portrait'].'&w=150&fltr[]=rcd|16|0', $phpThumbBase.'?src='.$img['portrait'].'&w=150&fltr[]=gray&fltr[]=rcd|8|1'), 'description' => 'ReduceColorDepth filter; original vs. 16-color dither vs. 16-color nodither vs. 4-gray dither'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['levels1'].'&w=150&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100', $phpThumbBase.'?src='.$img['levels1'].'&w=150&fltr[]=lvl|*|0&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100', $phpThumbBase.'?src='.$img['levels1'].'&w=150&fltr[]=lvl|*|1&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100', $phpThumbBase.'?src='.$img['levels1'].'&w=150&fltr[]=lvl|*|2&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100', $phpThumbBase.'?src='.$img['levels1'].'&w=150&fltr[]=lvl|*|3&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100', "\n", $phpThumbBase.'?src='.$img['levels2'].'&w=150&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100', $phpThumbBase.'?src='.$img['levels2'].'&w=150&fltr[]=lvl|*|0&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100', $phpThumbBase.'?src='.$img['levels2'].'&w=150&fltr[]=lvl|*|1&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100', $phpThumbBase.'?src='.$img['levels2'].'&w=150&fltr[]=lvl|*|2&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100', $phpThumbBase.'?src='.$img['levels2'].'&w=150&fltr[]=lvl|*|3&fltr[]=hist|rgb||||BR|100&fltr[]=hist|*||||BL|100'), 'description' => 'original vs. Levels filter methods (0=Internal RGB; 1=Internal Grayscale; 2=ImageMagick Contrast-Stretch; 3=ImageMagick Normalize)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['portrait'].'&w=200', $phpThumbBase.'?src='.$img['portrait'].'&w=200&fltr[]=lvl', $phpThumbBase.'?src='.$img['portrait'].'&w=200&fltr[]=wb'), 'description' => 'original vs. Levels vs. White Balance'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=300&fltr[]=hist|rgb', $phpThumbBase.'?src='.$img['levels1'].'&w=200&fltr[]=hist|*'), 'description' => 'histograms of RGB vs. grayscale'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=300&fltr[]=edge'), 'description' => 'Edge Detect filter'.$php5_or_IM.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=300&fltr[]=emb'), 'description' => 'Emboss filter'.$php5_or_IM.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=300&fltr[]=mean'), 'description' => 'Mean Removal filter'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=300&fltr[]=smth'), 'description' => 'Smooth filter'.$only_php500.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=gam|0.6', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=gam|1.6'), 'description' => 'Gamma corrected to 0.6 vs. 1.6'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=brit|50', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=brit|-50'), 'description' => 'Brightness filter (original vs. +50 vs. -50)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=cont|50', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=cont|-50'), 'description' => 'Contrast filter (original vs. +50 vs. -50)'.$only_gd2); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['portrait'].'&w=200&fltr[]=over|'.$img['frame1'].'|0', $phpThumbBase.'?src='.$img['portrait'].'&w=200&fltr[]=over|'.$img['frame2'].'|1'), 'description' => 'Overlay vs. Underlay

    Original over/under images:
    '.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=wmt|phpThumb|18|C|FF0000|loki.ttf|100|5|20&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=wmt|'.rawurlencode('☺♫ǖڞ').'|40|L|FF0000|arial.ttf|100&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=wmt|copyright+'.date('Y').'|3|BR|00FF00||50&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=wmt|copyright+'.date('Y').'%0AphpThumb()|3|L|00FFFF&f=png'), 'description' => 'Text overlay, TTF and built-in fonts, unicode characters (rawurlencoded HTMLentities), multiple lines, metacharacters (height, width)'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=wmt|thumbnail+=+^Xx^Y|3|BR|00FFFF||50&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=wmt|click%0Ahere%0A^FkkB|10|L|FF00FF|arial.ttf|100|0||333399|50|y&f=png', $phpThumbBase.'?src='.$img['landscape'].'&w=200&fltr[]=wmt|resized:+^Xx^Y+to+^xx^y|10|B|FFFFFF|arial.ttf|100|0||000000|100|x&f=png'), 'description' => 'metacharacters (height, width), background color, background extend'.$only_gd); +$Examples[] = array('getstrings' => array($phpThumbBase.'?new=FF0000&w=100&h=50&fltr[]=bvl|10&fltr[]=wmt|hello|14|C|00FFFF|arial.ttf&f=png', $phpThumbBase.'?new=FF0000|25&w=150&h=50&fltr[]=bvl|10&fltr[]=wmt|25%+opaque|14|C|0066FF|arial.ttf&f=png'), 'description' => 'Image created with "new", red background, bevel, TTF text'.$only_gd); + +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['bmp'].'&w=200'), 'description' => 'BMP source, width=200px'); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['tiff'], $phpThumbBase.'?src='.$img['tiff'].'&w=200&aoe=1'), 'description' => 'TIFF source, width=200px'.$only_im); +$Examples[] = array('getstrings' => array($phpThumbBase.'?src='.$img['wmf'].'&w=200'), 'description' => 'WMF source, width=200px'.$only_im); +//$Examples[] = array('getstrings' => array(''), 'description' => ''); + +foreach ($Examples as $key => $ExamplesArray) { + echo '#'.$key.''; + echo '
    '; + $text = ''; + foreach ($ExamplesArray['getstrings'] as $dummy => $GETstring) { + if ($GETstring == "\n") { + echo '
    '; + $text .= "\n"; + } else { + echo ''; + echo ''; + echo ' '; + $text .= ''."\n"; + } + } + echo '
    '; + echo '
    '.htmlentities($text).'
    '; + echo $ExamplesArray['description'].'
    '; + echo '


    '; +} + +$PATH_INFO_examples = array( + 'fltr[]=sep;200x200;'.$img['portrait'], + 'f=png;fltr[]=wmt|hello;fltr[]=flip|y;fltr[]=wmt|hello;200x100;new=FF00FF', +); + +echo '#pathinfo'; +echo '
    '; +foreach ($PATH_INFO_examples as $key => $value) { + echo ' '; +} +echo '
    '; +echo '
    ';
    +foreach ($PATH_INFO_examples as $key => $value) {
    +	echo htmlentities('  ')."\n";
    +}
    +echo '
    '; +echo 'PATH_INFO example
    '; +echo '


    '; + +?> + + +
    + + + + + + + + + + + + + + + + +
    + Illustration of potential difference between GD1.x and GD2.x
    + In most cases the thumbnails produced by phpThumb() on GD v1.x are perfectly + acceptable, but in some cases it may look ugly. Diagonal lines and reducing a + very large source image increase chance for bad results (the house/sky picture + has both problems). Here are three static examples: +
    GD v2.0.15kayak.jpg generated with phpThumb() on GD v2.0.15bottle.jpg generated with phpThumb() on GD v2.0.15sky.jpg generated with phpThumb() on GD v2.0.15
    GD v1.6.2kayak.jpg generated with phpThumb() on GD v1.6.2bottle.jpg generated with phpThumb() on GD v1.6.2sky.jpg generated with phpThumb() on GD v1.6.2

    +
    +
    + +Demo of phpThumb.demo.showpic.php
    +
    +'; +echo '(mouse-over to see calling parameters)
    '; +echo '
    '; +$SmallParams = array( + 'unmodified' => '', + 'text watermark' => '&fltr[]=wmt|Watermark|20|C|FF0000|arial.ttf|100', +); +foreach ($SmallParams as $description => $moreparams) { + echo ''.htmlentities($description).' '; +} +?> +
    +
    +'; +echo '(mouse-over to see calling parameters)
    '; +echo '
    '; +$BigParams = array( + 'unmodified' => '', + 'width=800' => '&w=800', + 'width=200, grayscale' => '&w=200&fltr[]=gray', +); +foreach ($BigParams as $description => $moreparams) { + echo ''.htmlentities($description).' '; +} +?> +
    +
    +'; +foreach ($img as $key => $value) { + echo '
  • '.basename($value).'
  • '; +} +echo '
    '; +?> + + \ No newline at end of file diff --git a/common/phpThumb/demo/phpThumb.demo.gallery.php b/common/phpThumb/demo/phpThumb.demo.gallery.php new file mode 100644 index 0000000..cff2db3 --- /dev/null +++ b/common/phpThumb/demo/phpThumb.demo.gallery.php @@ -0,0 +1,94 @@ + + + + phpThumb :: sample photo gallery demo + + + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.gallery.php // +// James Heinrich // +// // +// Demo showing basic usage of phpThumb in a photo gallery // +// // +////////////////////////////////////////////////////////////// + +$basedir = '/demo/images/'; // webroot-relative path to main images directory (only this and subdirectories of this will be displayed) +$thumb = '/demo/phpThumb.php'; // webroot-relative path to "phpThumb.php" +$popup = '/demo/demo/phpThumb.demo.showpic.php'; // webroot-relative path to "phpThumb.demo.showpic.php" (only used if $use_popup == true) +$thumbnailsize = 120; // size of thumbnails in pixels when browsing gallery +$displaysize = 480; // size of large image display (popup or plain image) after clicking on thumbnail +$use_popup = true; // if true, open large image in self-resizing popup window; if false, display larger image in main window + +////////////////////////////////////////////////////////////// + +$dirlimit = realpath(@$_SERVER['DOCUMENT_ROOT'].'/'.$basedir); + +$captionfile = $_SERVER['DOCUMENT_ROOT'].'/'.$basedir.(@$_REQUEST['dir'] ? $_REQUEST['dir'].'/' : '').'captions.txt'; +if (file_exists($captionfile)) { + $filecontents = file($captionfile); + foreach ($filecontents as $key => $value) { + @list($photo, $caption) = explode("\t", $value); + $CAPTIONS[$photo] = $caption; + } +} + +if (@$_REQUEST['pic']) { + + echo ''.htmlentities(@$CAPTIONS[$_REQUEST['pic']] ? $CAPTIONS[$_REQUEST['pic']] : $_REQUEST['pic']).'
    '; + echo '
    '.htmlentities(@$CAPTIONS[$_REQUEST['pic']]).'
    '; + +} else { + + $currentdir = realpath(@$_SERVER['DOCUMENT_ROOT'].'/'.$basedir.@$_REQUEST['dir']); + if (!ereg('^'.preg_quote($dirlimit), $currentdir)) { + echo 'Cannot browse to "'.htmlentities($currentdir).'"
    '; + } elseif ($dh = @opendir($currentdir)) { + $folders = array(); + $pictures = array(); + while ($file = readdir($dh)) { + if (is_dir($currentdir.'/'.$file) && ($file{0} != '.')) { + $folders[] = $file; + } elseif (eregi('\.(jpe?g|gif|png|bmp|tiff?)$', $file)) { + $pictures[] = $file; + } + } + closedir($dh); + if (ereg('^'.preg_quote($dirlimit), realpath($currentdir.'/..'))) { + echo 'Parent directory
    '; + } + if (!empty($folders)) { + echo ''; + } + if (!empty($pictures)) { + foreach ($pictures as $file) { + echo ''.(@$CAPTIONS[$file] ? '' : '').'
    '.htmlentities($CAPTIONS[$file]).'
    '; + if ($use_popup) { + echo ''; + } else { + echo ''; + } + echo ''.htmlentities(@$CAPTIONS[$file] ? $CAPTIONS[$file] : $file).''; + echo '
    '; + } + echo '
    '; + } else { + echo 'No pictures in "'.htmlentities(str_replace(realpath(@$_SERVER['DOCUMENT_ROOT']), '', realpath(@$_SERVER['DOCUMENT_ROOT'].'/'.$basedir.@$_REQUEST['dir']))).'"'; + } + } else { + echo 'failed to open "'.htmlentities($basedir).'"'; + } + +} +?> + + \ No newline at end of file diff --git a/common/phpThumb/demo/phpThumb.demo.object.php b/common/phpThumb/demo/phpThumb.demo.object.php new file mode 100644 index 0000000..42bf18d --- /dev/null +++ b/common/phpThumb/demo/phpThumb.demo.object.php @@ -0,0 +1,80 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.object.php // +// James Heinrich // +// // +// Example of how to use phpthumb.class.php as an object // +// // +////////////////////////////////////////////////////////////// + +// Note: phpThumb.php is where the caching code is located, if +// you instantiate your own phpThumb() object that code is +// bypassed and it's up to you to handle the reading and +// writing of cached files. + + + +require_once('../phpthumb.class.php'); + +// create 3 sizes of thumbnail +$thumbnail_widths = array(160, 320, 640); +$capture_raw_data = false; // set to true to insert to database rather than render to screen or file (see below) +foreach ($thumbnail_widths as $thumbnail_width) { + + // Note: If you want to loop through and create multiple + // thumbnails from different image sources, you should + // create and dispose an instance of phpThumb() each time + // through the loop and not reuse the object. + $phpThumb = new phpThumb(); + + // set data + $phpThumb->setSourceFilename($_FILES['userfile']['tmp_name']); + // or $phpThumb->setSourceData($binary_image_data); + // or $phpThumb->setSourceImageResource($gd_image_resource); + + // set parameters (see "URL Parameters" in phpthumb.readme.txt) + $phpThumb->setParameter('w', $thumbnail_width); + //$phpThumb->setParameter('h', 100); + //$phpThumb->setParameter('fltr', 'gam|1.2'); + + // set options (see phpThumb.config.php) + // here you must preface each option with "config_" + $phpThumb->setParameter('config_output_format', 'jpeg'); + $phpThumb->setParameter('config_imagemagick_path', '/usr/local/bin/convert'); + //$phpThumb->setParameter('config_allow_src_above_docroot', true); // needed if you're working outside DOCUMENT_ROOT, in a temp dir for example + + // generate & output thumbnail + $output_filename = './thumbnails/'.basename($_FILES['userfile']['name']).'_'.$thumbnail_width.'.'.$phpThumb->config_output_format; + if ($phpThumb->GenerateThumbnail()) { // this line is VERY important, do not remove it! + $output_size_x = ImageSX($phpThumb->gdimg_output); + $output_size_y = ImageSY($phpThumb->gdimg_output); + if ($output_filename || $capture_raw_data) { + if ($capture_raw_data && $phpThumb->RenderOutput()) { + // RenderOutput renders the thumbnail data to $phpThumb->outputImageData, not to a file or the browser + mysql_query("INSERT INTO `table` (`thumbnail`) VALUES ('".mysql_escape_string($phpThumb->outputImageData)."') WHERE (`id` = '".$id."')"); + } elseif ($phpThumb->RenderToFile($output_filename)) { + // do something on success + echo 'Successfully rendered:
    '; + } else { + // do something with debug/error messages + echo 'Failed (size='.$thumbnail_width.'):
    '.implode("\n\n", $phpThumb->debugmessages).'
    '; + } + } else { + $phpThumb->OutputThumbnail(); + } + } else { + // do something with debug/error messages + echo 'Failed (size='.$thumbnail_width.').
    '; + echo '
    '.$phpThumb->fatalerror.'
    '; + echo '

    '; + } + + // remember to unset the object each time through the loop + unset($phpThumb); +} + +?> \ No newline at end of file diff --git a/common/phpThumb/demo/phpThumb.demo.object.simple.php b/common/phpThumb/demo/phpThumb.demo.object.simple.php new file mode 100644 index 0000000..7e2e2c2 --- /dev/null +++ b/common/phpThumb/demo/phpThumb.demo.object.simple.php @@ -0,0 +1,40 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.object.simple.php // +// James Heinrich // +// // +// Simplified example of how to use phpthumb.class.php as // +// an object -- please also see phpThumb.demo.object.php // +// // +////////////////////////////////////////////////////////////// + +require_once('../phpthumb.class.php'); + +$phpThumb = new phpThumb(); + +// set data +$phpThumb->setSourceFilename($_FILES['userfile']['tmp_name']); + +// set parameters (see "URL Parameters" in phpthumb.readme.txt) +$phpThumb->setParameter('w', $thumbnail_width); + +// generate & output thumbnail +$output_filename = './thumbnails/'.basename($_FILES['userfile']['name']).'_'.$thumbnail_width.'.'.$phpThumb->config_output_format; +if ($phpThumb->GenerateThumbnail()) { // this line is VERY important, do not remove it! + if ($phpThumb->RenderToFile($output_filename)) { + // do something on success + echo 'Successfully rendered to "'.$output_filename.'"'; + } else { + // do something with debug/error messages + echo 'Failed:
    '.implode("\n\n", $phpThumb->debugmessages).'
    '; + } +} else { + // do something with debug/error messages + echo 'Failed:
    '.$phpThumb->fatalerror."\n\n".implode("\n\n", $phpThumb->debugmessages).'
    '; +} + +?> \ No newline at end of file diff --git a/common/phpThumb/demo/phpThumb.demo.random.php b/common/phpThumb/demo/phpThumb.demo.random.php new file mode 100644 index 0000000..d3f2905 --- /dev/null +++ b/common/phpThumb/demo/phpThumb.demo.random.php @@ -0,0 +1,95 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb.demo.random.php // +// James Heinrich // +// // +// Display a random image from a specified directory. // +// Run with no parameters for usage instructions. // +// // +////////////////////////////////////////////////////////////// + +function SelectRandomImage($dirname='.', $portrait=true, $landscape=true, $square=true) { + // return a random image filename from $dirname + // the last 3 parameters determine what aspect ratio of images + // may be returned + $possibleimages = array(); + if ($dh = opendir($dirname)) { + while ($file = readdir($dh)) { + if (is_file($dirname.'/'.$file) && eregi('\.(jpg|jpeg|gif|png|tiff|bmp)$', $file)) { + if ($gis = @GetImageSize($dirname.'/'.$file)) { + if ($portrait && ($gis[0] < $gis[1])) { + // portrait + $possibleimages[] = $file; + } elseif ($landscape && ($gis[0] > $gis[1])) { + // landscape + $possibleimages[] = $file; + } elseif ($square) { + // square + $possibleimages[] = $file; + } + } + } + } + closedir($dh); + } + if (empty($possibleimages)) { + return false; + } + if (phpversion() < '4.2.0') { + mt_srand(time()); + } + $randkey = mt_rand(0, count($possibleimages) - 1); + return realpath($dirname.'/'.$possibleimages[$randkey]); +} + +if (@$_REQUEST['dir']) { + if (is_dir($_REQUEST['dir'])) { + + if (!@$_REQUEST['o']) { + $_REQUEST['o'] = 'PLS'; + } + $_REQUEST['o'] = strtoupper($_REQUEST['o']); + $portrait = (strpos(@$_REQUEST['o'], 'P') !== false); + $landscape = (strpos(@$_REQUEST['o'], 'L') !== false); + $square = (strpos(@$_REQUEST['o'], 'S') !== false); + $randomSRC = SelectRandomImage($_REQUEST['dir'], $portrait, $landscape, $square); + if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + $randomSRC = str_replace('\\', '/', eregi_replace('^'.realpath(@$_SERVER['DOCUMENT_ROOT']), '', realpath($randomSRC))); + } else { + $randomSRC = str_replace(realpath(@$_SERVER['DOCUMENT_ROOT']), '', realpath($randomSRC)); + } + + $otherParams = array(); + foreach ($_GET as $key => $value) { + if (($key == 'dir') || ($key == 'o')) { + continue; + } + if (is_array($value)) { + foreach ($value as $vkey => $vvalue) { + $otherParams[] = urlencode($key).'['.urlencode($vkey).']='.urlencode($vvalue); + } + } else { + $otherParams[] = urlencode($key).'='.urlencode($value); + } + } + header('Location: ../phpThumb.php?src='.urlencode($randomSRC).'&'.implode('&', $otherParams)); + exit; + + } else { + die($_REQUEST['dir'].' is not a directory'); + } + +} else { + + echo 'Usage: '.basename($_SERVER['PHP_SELF']).'?dir=<directory>&<phpThumb parameters>&o=(P|L|S)

    Examples:
      '; + echo '
    • '.basename($_SERVER['PHP_SELF']).'?./images/&o=L (landscape images only)
    • '; + echo '
    • '.basename($_SERVER['PHP_SELF']).'?./images/&o=PS (portrait or square images only)
    • '; + echo '
    '; + +} + +?> diff --git a/common/phpThumb/demo/phpThumb.demo.showpic.php b/common/phpThumb/demo/phpThumb.demo.showpic.php new file mode 100644 index 0000000..c92f4db --- /dev/null +++ b/common/phpThumb/demo/phpThumb.demo.showpic.php @@ -0,0 +1,131 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +// // +// phpThumb.demo.showpic.php // +// James Heinrich // +// 23 Feb 2004 // +// // +// This code is useful for popup pictures (e.g. thumbnails // +// you want to show larger, such as a larger version of a // +// product photo for example) but you don't know the image // +// dimensions before popping up. This script displays the // +// image with no window border, and resizes the window to // +// the size it needs to be (usually better to spawn it // +// large (600x400 for example) and let it auto-resize it // +// smaller), and if the image is larger than 90% of the // +// current screen area the window respawns itself with // +// scrollbars. // +// // +// Usage: // +// window.open('showpic.php?src=big.jpg&title=Big+picture', // +// 'popupwindowname', // +// 'width=600,height=400,menubar=no,toolbar=no') // +// // +// See demo linked from http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// + +$phpThumbLocation = '../phpThumb.php?'; + +echo ''; +echo ''; +if (isset($_GET['title'])) { + echo ''.htmlentities($_GET['title']).''; + unset($_GET['title']); +} else { + echo ''.htmlentities('phpThumb :: popup window resizing demo').''; +} +?> + + + + + + $value) { + if (is_array($value)) { + foreach ($value as $key2 => $value2) { + $additionalparameters[] = $key.'[]='.SafeStripSlashes($value2); + } + } else { + $additionalparameters[] = $key.'='.SafeStripSlashes($value); + } + } + $imagesrc = $phpThumbLocation.implode('&', $additionalparameters); + + echo ''; +?> + + + +
    '; + echo 'document.writeln(\'\');'; + echo ''; + +} else { + + echo '
    ';
    +	echo 'Usage:

    '.$_SERVER['PHP_SELF'].'?src=filename&title=Picture+Title'; + echo '
    '; + +} + +?>
    + \ No newline at end of file diff --git a/common/phpThumb/demo/readme.demos.txt b/common/phpThumb/demo/readme.demos.txt new file mode 100644 index 0000000..b0cb84d --- /dev/null +++ b/common/phpThumb/demo/readme.demos.txt @@ -0,0 +1,49 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpThumb() included and related demos // +// /// +////////////////////////////////////////////////////////////// + +The phpThumb() distribution includes several demos, and it +should be self-evident what they do when you run them: + +* phpThumb.demo.demo.php - shows a wide variety of samples, + basically all the different features and filters of phpThumb. + Note: sample image files are not included in the distribution + but can be downloaded from http://phpthumb.sourceforge.net/demo + +* phpThumb.demo.check.php - configuration checker, will check + your config file and server configuration and warn of any + potential problems + +* phpThumb.demo.gallery.php - basic demonstration of a photo + gallery with ability to browse subdirectories. May use + phpThumb.demo.showpic.php for fullsize popup display + +* phpThumb.demo.showpic.php - auto-resizes a popup window to + match the dimensions of the image it is displaying + +* phpThumb.demo.object.php - example of how to call phpThumb + as an object. + +* phpThumb.demo.object.simple.php - simplified version of + phpThumb.demo.object.php with fewer options shown. + +* phpThumb.demo.random.php - select & display a random thumbnail + from a directory of images. + + + +Other people have created useful demos and/or extensions to +phpThumb(). Some of these I know of are: +(also see http://phpthumb.sourceforge.net for an updated list) + +* iManager/iBrowser - http://www.j-cons.com/news/ +* ThumbnailSelector - http://www.silisoftware.com/scripts/ThumbnailSelector +* Applejuice Build_Gallery - http://twofivethreetwo.com/?nav=scripts + +If you know of any others you think should be mentioned here +please let me know: info@silisoftware.com \ No newline at end of file diff --git a/common/phpThumb/docs/phpthumb.changelog.txt b/common/phpThumb/docs/phpthumb.changelog.txt new file mode 100644 index 0000000..1af45a4 --- /dev/null +++ b/common/phpThumb/docs/phpthumb.changelog.txt @@ -0,0 +1,1276 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// + + = structure change or important new feature +* = less important new feature or change + +v1.7.7 - December ??, 2006 + Added phpThumb.demo.gallery.php -- basic image gallery demo + Added option for image watermark for anti-hotlinking. See + phpThumb.config.php "nooffsitelink_watermark_src" + (thanks rik_helsenrad*be) + Added config option "imagemagick_use_thumbnail" to control + use of ImageMagick's "-thumbnail" command vs "-resize" (the + former discards non-visible metadata, the latter retains it) + Most times you want the smallest filesize so keep the default + setting (imagemagick_use_thumbnail==true) + (thanks niklasmysticalgarden*se) + * Bugfix [#1620056]: EnsureDirectoryExists() failed to create + some directory structures (thanks jeromylocallinux*com) + * Bugfix [#1620056]: CleanUpCacheDirectory() would not purge + files from subdirectories if (cache_directory_depth > 0) + (thanks kingsquareusers*sourceforge*net) + * Bugfix: nooffsitelink_* broken when running on non-standard + HTTP port (thanks marianbucur17yahoo*com) + + +v1.7.6 - December 09, 2006 + Added "sia" (Save Image As) parameter to provide default + filename when saving generated thumbnails + (thanks web_mkhotmail*com) + Changed "lvl" filter parameters, and added option to choose + between four different methods (two internal, two from + ImageMagick). Added configurable threshold parameter. + (thanks publicwoktiny*com for code for new internal method) + "wb" (White Balance) filter now processed by ImageMagick + * Changed GD max source pixels to 1/6 (from 1/5) available + memory, and changed SourceImageIsTooLarge() to account for + already-used memory (if known) + * More graceful error handling in object mode when source + larger than PHP memory limit and ImageMagick unavailable + (thanks djasondjason*com) + * Added ImageMagickFormatsList() + * CleanUpCacheDirectory() now also purges zero-byte orphan + files left over from aborted thumbnailings + * Bugfix [#1606069]: Changed default urlencoded space + character from "+" to "%20" + * Bugfix [#1608664]: "Unsupported operand types" in "wmi" + filter (thanks haydurhaydur*com; squidliberty) + * Bugfix: debug mode now supports text output in all modes + * Bugfix: ImageMagick creation attempted before GD creation + * Bugfix: no longer fails silently if GD creation runs out of + memory + * Bugfix: poor alpha rendering from PNG to GIF with ImageMagick + * Bugfix: "wb" filter had no effect when "lvl" filter applied + in ImageMagick instead of GD + + +v1.7.5 - October 03, 2006 + Deprecated parameters "err", "file", "goto" + Added broad cache directory feature (see phpThumb.config.php + "cache_directory_depth") to spread cache files across many + directories for improved performance and ability to store + very large numbers (30000+) of cached files + (thanks despoixopenxtrem*com) + phpThumb now follows HTTP redirects (status=302) to new + HTTP image URLs (configurable: config_http_follow_redirect) + (thanks shannahsfu*ca) + Added "rot" (ROTate) filter which is similar to "ra" parameter + but now allows rotation of output of other filters (for + example, rotate image after fltr[]=mask is applied) + (thanks markwoodjoint*ca) + Added WBMP output support (built-in GD or via ImageMagick) + (code was already mostly present, just was not allowed format) + [#1567113] "wmi" filter now accepts both x and y margins + and can be in pixels or percent of thumbnail dimensions + (thanks squidlibertyusers*sourceforge*net) + * "hist" filter now accepts both X and Y margins + * Added config variables: config_http_fopen_timeout = 10; + config_http_follow_redirect = true + * Changed MIME type for WBMP to image/vnd.wap.wbmp + * Bugfix: Check for GD format support before attempting output + * Bugfix: Opening HTTP source images with URL query parameters + was broken (eg: http://host/show?id=123) + (thanks ivo*beckersinfopractica*nl) + + +v1.7.4 - August 17, 2006 + Improved version of /demo/phpThumb.demo.showpic.php uses + phpThumb.php so any filters can be applied, as well as + resized image popups. + New file: /demo/javascript_api.js + Uses Javascript API by James Austin + (http://aspandjavascript.co.uk/javascript/javascript_api/) + Added "sfn" (Source Frame Number) parameter to specify + source frame in multi-frame/multi-page source formats, such + as GIF, TIFF, PDF, etc (thanks despoixopenxtrem*com) + Added "dpi" (Dots Per Inch) parameter to specify + rasterising resolution for vector source formats (PDF, WMF) + (requires ImageMagick) (thanks despoixopenxtrem*com) + * Added /demo/phpThumb.demo.object.simple.php + * Added debug points inside GenerateThumbnail + * Explicit error message for unsupported PDF source images + * Bugfix: SafeURLread broken with GETstring parameters in + fsockopen mode + * Bugfix: [#1540523] CleanUpCacheDirectory() does not delete + files as expected (thanks patricksleeusers*sourceforge*net) + * Bugfix: added useful error message when no source specified + in object mode (thanks infodoepud*co*uk) + * Bugfix: timeout value ignored in URLreadFsock() + * Bugfix: timeout missing in SafeURLread CURL part + * Bugfix: ImageMagick now checked with --version (not -version) + * Bugfix: better ImageMagick (numeric) version number matching + * Bugfix: noGD errors showing up when GD imagecreate functions + fail and ImageMagick not available + (thanks caseyygmail*com) + * Bugfix: "-thumbnail" parameter not present in older versions + of ImageMagick, now using -resize if -thumbnail unavailable + (thanks atombomb96btopenworld*com) + * Bugfix: "-resize" parameter requires explicit dimensions + ("100x100" instead of "100x") in older ImageMagick versions + (thanks atombomb96btopenworld*com) + * Bugfix: phpThumb crashed with no output if ImageMagick failed + to resize but output image larger than max_source_pixels + (thanks atombomb96btopenworld*com) + * Bugfix: phpThumb might die with no output on some large source + images when ImageMagick unavailable. + (thanks atombomb96btopenworld*com) + + +v1.7.3 - July 11, 2006 + * Now returns useful message for HTTP sources if 404-file- + not-found (or similar) errors occur + * Added new fsockopen() section in SafeURLread() + * Removed PNG alpha warning for IE 7 (alpha PNGs now work) + * Bugfix: ImageMagick failing version check and dumping text + output (thanks infodevsystem*net) + * Bugfix: curl_exec failing with text output + (thanks infodevsystem*net) + * Bugfix: workaround for PHP Bug #36102 (fopen(http) crash + in PHP v4.4.2 + * Bugfix: "Unknown image type identified by..." problem when + opening http:// source images + (thanks webmasterdanceage*com) + + +v1.7.2 - June 22, 2006 + [#1256693] Added $this->exif_raw_data which is returned + data from exif_read_data() on source image. + Requires PHP v4.2.0+ (thanks tebiusers*sourceforge*net) + Added $this->outputImageData and RenderOutput() to allow + easy outputting of thumbnail data to a database or such. + Call RenderOutput() instead of RenderToFile() and then + access raw data in $this->outputImageData + (thanks r*cremerswitch*nl) + Added 'crop' filter, which is applied after resizing (as + opposed to sx,sy,sw,sh which are before resizing) + (thanks scottscottjehl*com) + * Enable creating new images with PATH_INFO style call + (thanks edeninstyleit*com*au) + * Added warning message to encourage users not to use + full HTTP paths for "src" parameter + * Added fallback 'preg_quote' to phpthumb.functions.php in + case your PHP installation does not have preg_* functions + (thanks mortenemeskay*dk) + * Added fallback 'imagesavealpha' if GD < v2.0.1 + (thanks oliver*heegerweb*de) + * Added fallback 'imagealphablending' if GD < v2.0.1 + (thanks oliver*heegerweb*de) + * Added 'nocache' parameter that suppresses writing to cache + file, but only if high_security_enabled is set + (thanks federicodonelleschi*com) + * Attempt to detect supported ImageMagick features + (thanks simonjapancentre*com) + * Added temp dir detection to phpThumb.demo.check.php + * Added ImageMagick dir to phpThumb.demo.check.php + * Added ImageMagick features to phpThumb.demo.check.php + * Default (config_allow_src_above_docroot = true) when PHP + running in "cli" mode (thanks flobeegmail*com) + * Bugfix: [#1470791] 'iar' not working properly with + ImageMagick (thanks w1xusers*sourceforge*net) + * Bugfix: [#1498564] illegal characters in cache filenames + (thanks carl-evertusers*sourceforge*net) + * Bugfix: 'sx','sy','sw','sh','zc' cache parameters broken + (thanks federicodonelleschi*com) + * Bugfix: 'config_max_source_pixels' incorrectly handled + (thanks oliver*heegerweb*de) + * Bugfix: 'aoe' not working properly + (thanks w1xusers*sourceforge*net) + * Bugfix: setParameter() was broken for arrays + * Bugfix: setSourceFilename() wasn't setting 'src' + * Bugfix: suppress stat()-related file permission + notices (thanks lancemainecoastdesign*com) + * Bugfix: image format now initialized during ErrorImage() + * Bugfix: domain matching now case-insensitive + * Bugfix: some versions of ImageMagick not detected + (thanks arvidfys*ku*dk) + * Bugfix: sometimes no image returned in safe_mode + (thanks bkainersgmail*com) + * Bugfix: 'far' not always handled correctly + (thanks matthew*newtonrealworldweb*com) + * Bugfix: PATH_INFO method not working if no filters specified + (thanks jjimenezpracticaldata*com) + * Bugfix: first (internal) call to ImageMagickVersion() failed + under Windows + * Bugfix: Images source-cropped AND resized with ImageMagick were + wrong size (cropped size, not resized size) + (thanks joao*saleirowebfuel*pt) + * Bugfix: stat() warnings in CleanUpCacheDirectory() + (thanks christianhss-haage*de) + * Bugfix: $PHPTHUMB_DEFAULTS not working when no other processing + parameters specified (thanks tbittnerscox*net) + + +v1.7.1 - March 16, 2006 + * /demo/phpThumb.demo.check.php now checks: + - server software + - local and master config values (with ini_get and + get_cfg_var respectively) (thanks nEUTRongmx*tm) + - existance of assorted PHP functions and explains their + importance + * Bugfix: config_error_die_on_error now defaults to FALSE to + prevent object-mode errors dying in an error image + (thanks moshtobt*de; riteshgupta1974gmail*com) + * Bugfix: setParameter() now handles array parameters (such + as 'fltr') by appending $value to $parameter + * Bugfix: /demo/phpThumb.demo.check.php incorrect CURL value + under PHP5 (thanks nEUTRongmx*tm) + * Bugfix: [#1439110] Limit fread() calls to 8kB + (see http://bugs.php.net/bug.php?id=35859) + (thanks andig2users*sourceforge*net) + * Bugfix: Prevent RenderToFilename() from trying to render + to URLs (thanks Tim*Masseyitrm*co*uk) + * Bugfix: [#1438657] missing path in phpThumbURL() + (thanks terracesusers*sourceforge*net) + * Bugfix: zoomcrop was broken for non-square output + (thanks alisonsemidivine*com, federicodonelleschi*com) + * Bugfix: suppress error messages when stat access to temp + dir is disabled (thanks rfinevnuinc*com) + * Bugfix: ImageMagick processing was broken for source + images of types not supported by GetImageSize + (thanks rfinevnuinc*com) + +v1.7.0 - February 15, 2006 + ImageMagick output is used directly far more frequently + for much improved speed and minor quality improvement. + ImageMagick now processes most of the image filters if + possible (will fall back to GD methods if unavailable) + GD support is now optional if ImageMagick is installed. + Known limitations include: + - no support for HTTP source images + - ICO output is buggy (in some ImageMagick versions) + - most &fltr[] filters don't work at all + - 'ar', 'ra', 'far' don't work + Added output support for ICO (icon) format (&f=ico). + Currently only supports single-image icons, but multi- + resolution support may be added in future versions + New file: phpthumb.ico.php + Added output support for BMP (bitmap) format (&f=bmp). + Currently only supports 24-bit RGB format (for simplicity) + Added new configuration & compatability checker + New file: demo/phpThumb.demo.check.php + * ImageMagick-generated thumbnails now have extra hidden + contents (EXIF data, etc) stripped (by using -thumbnail + instead of -resize) resulting in smaller filesizes + * Added background fill color, opacity and extent options to + 'wmt' filter (thanks craigpc-fanatics*com) + * Added metacharacter (^*) support for 'wmt', currently: + source filesize in bytes (^Fb), kB (^Fk), MB (^Fm), + source image width (^X), source image height (^Y), + thumbnail width (^x), thumbnail height (^y) and caret (^^) + (Feature Request #1357815) + (thanks ticklemeozmousers*sourceforge*net) + * Moved ImageDestroy call from OutputThumbnail to end of + phpThumb.php to allow multiple calls to OutputThumbnail + * Added config_http_user_agent for site with browsersniffers + (thanks redrobgmail*com) + * Added $PHPTHUMB_CONFIG['disable_pathinfo_parsing'] (default + false) which disables parsing $_SERVER[PATH_INFO] for + parameters. If you want to parse PATH_INFO, set to false + * Added $PHPTHUMB_CONFIG['disable_imagecopyresampled'] (default + false) which replaces ImageCopyResampled with + ImageCopyResampleBicubic for buggy PHP-GD versions + (thanks g*pelagattinetface*it) + * Added $PHPTHUMB_CONFIG['cache_prefix'] to allow sharing of + cache files across virtual servers (Feature Request #1395332) + (thanks doggyfrusers*sourceforge*net) + * Added $PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] with + default=true (increased speed) to allow direct passthru of + images that don't have GD support. (Feature Request #1396446) + (thanks zedboyusers*sourceforge*net) + * Removed $PHPTHUMB_CONFIG['cache_differentiate_offsite'] because + it is now automatically tied in with nooffsitelink_enabled + (thanks doggysworldlibertysurf*fr) + * Removed phpThumb.demo.cacheconvert2.php + * Debug messages are now passed back from filters + * $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] now + defaults to true for much-improved cached performance + (thanks redrobgmail*com) + * $PHPTHUMB_CONFIG['cache_differentiate_offsite'] now defaults + to false + * Added $PHPTHUMB_DEFAULTS['ar']='x' to phpThumb.config.php.default + * Added ImageDestroy($this->gdimg_source) to GenerateThumbnail() + to save memory before applying image filters + * gd_info() no longer member of phpthumb_functions + * cache files now default to using SERVER_NAME without 'www.' + * phpUnsharpMask::applyUnsharpMask() should be faster under PHP5 by + using ImageFilter(IMG_FILTER_GAUSSIAN_BLUR) when radius==1 + * Added alternate CURL method for HTTP source images if + allow_url_fopen is disabled (thanks webwebermotiondraw*com) + * Replaced $this->osslash with DIRECTORY_SEPARATOR constant + * Bugfix: [#1398327] 'new' got broken (1x1 images) + * Bugfix: [#1412552] HTTP source images with special characters were + not getting urlencoded + * Bugfix: ImageSaveAlpha errors on GD v2.0.0 + * Bugfix: phpThumbDebug now entirely disabled if high_security=true + * Bugfix: source images with transparency lost transparency when + rotated (thanks roalklyahoo*com) + * Bugfix: square source images were not resized when only (w|h)(p|l) + parameters passed + * Bugfix: source images are passed through unmodified in more cases + * Bugfix: ImageMagick not used on systems where it exists outside + defined open_basedir + * Bugfix: ImageMagickVersion() now returns correct versionstring + * Bugfix: ImageMagick warnings no longer cause ImageMagick to fail + * Bugfix: ErrorImage no longer fatal to phpThumbDebug + * Bugfix: "Array to string conversion" in foreach($a as $v) loops + (thanks zeeshantargetedmedia*co*uk) + * Bugfix: safe mode warnings in ImageCreateFromStringReplacement + (thanks adminalex-home*net) + * Bugfix: nooffsitelink broken if !nooffsitelink_require_refer + (thanks deprongmx*net) + * Bugfix: phpThumb failed when magic_quotes_runtime=true + (thanks stansawyeryahoo*com) + * Bugfix: several issues with HTTP image sources + (thanks redrobgmail*com) + * Bugfix: phpThumb_tempnam() would return incomplete temp filenames + under Windows, which may result in orphaned zero-byte temp files + in C:\ if multiple drives exist + +v1.6.2 - November 24, 2005 + Animated GIF output is now possible if ImageMagick is + available and no filters (other than resize) are applied + (thanks brandenbassgmail*com for idea) + * Added $PHPTHUMB_CONFIG['cache_force_passthru'] to work + around cached-image-only-works-second-time issue + (thanks yako11y11*com) + * Bugfix: black borders on some image edges + (thanks atelierdelirius*ch && chuckcatalyststudio*com) + * Bugfix: uncaught PHP warning in RenderToFile DebugMessage + * Bugfix: allow phpThumbDebug in noGD PHP installations + * Bugfix: 'hash' warning in high_security mode + (thanks bernhardwtf*at) + * Bugfix: non-TTF rotated text watermarks now work (unrotated) + with no warnings if ImageRotate is unavailable + (thanks aparviaiusers*sourceforge*net) + +v1.6.1 - August 26, 2005 + Filters now use GD functions where available (using + ImageFilter, only available in PHP v5.0.0+ with bundled + version of GD). Enabled for: colorize, negative, + grayscale, brightness, contrast, gaussian blur, selective + blur, mean removal (thanks donlaurmac*com) + Added config_prefer_imagemagick (defaults=true) + Added phpthumb_filters::Grayscale() 'gray' + Added phpthumb_filters::ReduceColorDepth() 'rcd' + Added phpthumb_filters::Brightness() 'brit' + Added phpthumb_filters::Contrast() 'cont' + Added phpthumb_filters::Saturation() 'sat' + Added phpthumb_filters::EdgeDetect() 'edge' [PHP5 only] + Added phpthumb_filters::BlurGaussian() 'gblr' [PHP5 only] + Added phpthumb_filters::BlurSelective() 'gblr' [PHP5 only] + Added phpthumb_filters::MeanRemoval() 'mean' [PHP5 only] + Added phpthumb_filters::Smooth() 'smth' [PHP5 only] + * New timing debug info in phpThumbDebug + * Added config_cache_differentiate_offsite + * config_die_on_error now defaults to false + * ResolveSource works better + * cache filenames with 'fltr' parameters have changed + * Filters now skip processing if amount=0 or similar + * [#1263051] 'far' now accepts L,R,T,B,C as values giving + alignment of left/right/top/bottom/center respectively. + Old value of '1' defaults to centered + (thanks webgrappausers*sourceforge*net) + * Bugfix: RenderToFile() now fails properly when output format + is unknown + * Bugfix: PNG transparency wasn't working with 'far' + * Bugfix: source images with EXIF thumbnails that differ in + aspect ratio no longer use EXIF thumbnails as source unless + no other options exist + * Bugfix: setting 'src' with setParameter now invokes + setSourceFilename to properly set $this->sourceFilename + (thanks Gazou) + * Bugfix: 'zc' had poor quality when used with ImageMagick + * Bugfix: 'aoe' parameter broken when not using ImageMagick + (thanks frankieali4hotmail*com) + * Bugfix: fixed issue with symbolic links + (thanks hornet136gmail*com) + * Bugfix: config_max_source_pixels now defaults to same + calculation as used in phpThumb.config.php + (thanks vukshahotmail*com) + * Bugfix: Offsite cached thumbnails no longer use unique + referer (now either nothing or "_offsite") + (thanks swaayeyahoo*com) + * Bugfix: "Unknown image type identified by ] + where is the target hex color to white balance + on, this color is what "should be" white, or light + gray. The filter attempts to maintain brightness so + any gray color can theoretically be used. If is + omitted the filter guesses based on brightest pixels + in each of RGB + Cached files are used by a Location header instead of + being passed through phpThumb.php using readfile + (thanks newtnthrillnerds*com) + * Added 'cache_source_filemtime_ignore_local' and + 'cache_source_filemtime_ignore_remote' configurations + to ignore source modification and/or removal + (thanks raynerapegmail*com) + * Added 'md5s' parameter, which is the MD5 hash of the + source image -- if this parameter is passed with the + hash of the source image then the source image is not + checked for existance or modification and the cached + file is used (if available). If 'md5s' is passed an + empty string then phpThumb.php dies and outputs the + correct MD5 hash value. This parameter is the single- + file equivalent of 'cache_source_filemtime_ignore_*' + configuration paramters (thanks raynerapegmail*com) + * Added /demo/phpThumb.demo.object.php + * Unused parameter 'bgt' removed + * Added empty /cache/source/ directory to distribution + * Added /demo/ and /docs/ and /fonts/ directories + * Set default config_use_exif_thumbnail_for_speed = false + * Bugfix: Wrapped output buffering around all + include_once calls to prevent headers getting sent + accidentally + * Bugfix: md5_file and imagecolorallocatealpha calls + were undefined under PHP v4.1.x (thanks tomemile*com) + * Bugfix: default 'f' parameter ('jpeg') overrode + config_output_format in object mode + (thanks mailmmjaeger*com) + * Bugfix: suppressed error message for IIS shell_exec + errors (thanks tomemile*com) + * Bugfix: Added PHP version check for stream_set_timeout + for HTTP sources (thanks raynerapegmail*com) + * Bugfix: overlay margins of 0.5-1.0 cause invalid image + dimensions error (thanks mailmmjaeger*com) + * Bugfix: underlay margins were not working + (thanks mailmmjaeger*com) + * Bugfix: [#1187735] EXIF thumbnails were incorrectly + output to the browser directly if requested thumbnail + exactly matched EXIF dimensions + (thanks rebootusers*sourceforge*net) + +v1.5.2 - April 20, 2005 + phpThumb.config.php is renamed to + phpThumb.config.php.default to prevent accidental + overwriting. Please migrate your old settings to the new + file, delete your old config and rename the default to + phpThumb.config.php + Added new filters: + - 'blur' (Blur) [ex: &fltr[]=blur|] + where (0 < < 25) (default = 1) + (thanks thoensinetcom*no for code) + - 'hist' (Histogram) + [ex: &fltr[]=hist|||||||] + Where is the color band(s) to display, from back + to front (one or more of "rgba*" for Red Green Blue + Alpha and Grayscale respectively); + is a semicolon-seperated list of hex colors to + use for each graph band (defaults to FF0000, 00FF00, + 0000FF, 999999, FFFFFF respectively); + and are the width and height of the overlaid + histogram in pixels, or if <= 1 then percentage of + source image width/height; + is the alignment (same as for "wmi" and "wmt"); + is opacity from 0 to 100; + is the edge (and inter-tile) margin in percent + - 'over' (OVERlay/underlay image) overlays an image on + the thumbnail, or overlays the thumbnail on another + image (to create a picture frame for example) + [ex: &fltr[]=over||||] + where is the image filename; is "0" (default) + for overlay the image on top of the thumbnail or "1" + for overlay the thumbnail on top of the image; is + the margin - can be absolute pixels, or if < 1 is a + percentage of the thumbnail size [must be < 0.5] + (default is 0 for overlay and 10% for underlay); + is opacity (0 = transparent, 100 = opaque) + (thanks raynerapegmail*com, shabazz3msu*edu) + - 'gray' (GRAYscale) [ex: &fltr[]=gray] + is an alias to 100% desaturation + * New configuration 'cache_source_directory' allows the + unprocessed source image to be cached when source is + HTTP or from a database (thanks raynerapegmail*com) + * Added 'cache' subdirectory to phpThumb distribution + since this is the default location for the cache + folder. + * Default value for config_error_die_on_source_failure + changed to true (thanks shabazz3msu*edu) + * Added checks to make sure $this->gdimg_output is a + resource before allowing calls to RenderToFile or + OutputThumbnail + * Better error messages when phpThumb.config.php missing + * Bugfix: watermark overlay margins were wrong + * Bugfix: 'lvl' filter no longer processes if not needed + * Bugfix: off-server thumbnail error message was wrong + * Bugfix: several PHP safe mode fixes + (thanks virginiaalertbutnotalarmed*com) + * Bugfix: cache filenames broken for filter parameters + with paths (thanks srcericusers.sourceforge.net) + +v1.5.1 - April 06, 2005 + * Added some security upgrades: + - 'config_*' parameters cannot be passed by GETstring + - 'config_nooffsitelink_require_refer' is a new option + (disabled by default) that only allows calls to + phpThumb() from a refering domain listed in + 'config_nooffsitelink_valid_domains' + - disallowed paramters now generate an error image if + present in the GETstring + - 'high_security_enabled' if set to true enabled new + mode of verification, and requires a small function + to generate a hash for calls to phpThumb: + echo ''; + This function is supplied at the bottom of + phpThumb.config.php (thanks paulstonie*co*uk) + Added new parameter "new" (phpThumb.php only) which can + create a new image without using "src" parameter. Set + "&new=|" where is the background hex color, + is (optional) opacity (0=transparent, 100=opaque). + (thanks mailmmjaeger*com) + Added new filters: + - 'sep' (Sepia) [ex: &fltr[]=sep||] + where is a number between 0 and 100 for the + amount of colorization (default=50), and is + the hex color to colorize to (default=A28065). + (thanks mailmmjaeger*com) + - 'lvl' (Levels) [ex: &fltr[]=lvl||| + where can be one of 'r', 'g', 'b', 'a' (for + Red, Green, Blue, Alpha respectively), or '*' for all + channels based on average grayscale value (default). + and are the clip points for the levels + (range = 0-255) and are set to clip 0.1% of each end + by default. Use -1 for min and/or max to invoke auto- + detect mode. Using default parameters (&fltr[]=lvl) + is similar to Auto Contrast in Adobe Photoshop. + * Bugfix: Image MIME header was incorrect for cached + images. + * Bugfix: Cache was broken for images pulled from a + database in phpThumb.php + (thanks dragutin*cvetkovicdragontech-ltd*com) + * Bugfix: Hotlink/Offsite prevention was broken when + image was already cached. + * Bugfix: ImageMagick path was incorrect in some cases + (thanks joshgtwcny*rr*com) + * Bugfix: ProportionalResize() in phpthumb.functions.php + had a broken check for default values + (thanks Bert*Claeysarinso*com) + * Bugfix: transparency now preserved for GIF & PNG input + (thanks tristancyrax*ch) + * Bugfix: transparency now supported for GIF output + (thanks j_ivanovabv*bg) + * Bugfix: alpha transparency could be lost in ApplyMask() + (thanks analyzerxgmail*com) + * Bugfix: errors on 16/32-bit BMPs + (thanks matthellstrominc*com) + * Bugfix: Added datestamp to cached filenames for remote + (HTTP) files, and better warning for caching + (thanks a*gambinoabramo*it) + * Faster BMP parsing (thanks sgeppertmail*utexas*edu) + * Added 'error_die_on_source_failure' configuration to + allow invalid source images to show an error rather + than output unmodified source image. + (thanks mindpixelgmail*com) + * Added $phpThumb->fatalerror which will contain the + text of the fatal error if 'error_die_on_error' is + false. (thanks mindpixelgmail*com) + +v1.5.0 - February 4, 2005 + * Added new filter parameter 'fltr' that is an array and + can apply multiple effects in sequence. Current filters + that can be called are: + - 'gam' (Gamma Correction) [ex: &fltr[]=gam|] + where can be a number >0 to 10+ (default 1.0) + - 'ds' (DeSaturate) [ex: &fltr[]=ds|] + where is a number between zero (no change) + and 100 (complete desaturation -- grayscale), or it + can be a negative number for saturation boost. + (thanks mailmmjaeger*com) + - 'clr' (Colorize) [ex: &fltr[]=clr||] + where is a number between 0 and 100 for the + amount of colorization, and is the hex color + to colorize to. (thanks mailmmjaeger*com) + - 'neg' (Negative) [ex: &fltr[]=neg] + inverts the color + - 'th' (ThresHold) [ex: &fltr[]=th|] (range 0-255) + every grayscale pixel brighter than is set to + white, every darker pixel is set to black + (thanks mailmmjaeger*com) + - 'usm' (UnSharpMask) [ex: &fltr[]=usm|||] + where is the amount (default = 80), is the + radius (default = 0.5), is the threshold + (default = 3). + - 'wmi' (WaterMarkImage) + [ex: &fltr[]=wmi||||] where is the + filename of the image to overlay, is the + alignment (one of BR, BL, TR, TL, C, R, L, T, B, * + where B=bottom, T=top, L=left, R=right, C=centre, + *=tile), is opacity from 0 to 100, is the + edge (and inter-tile) margin in percent + - 'wmt' (WaterMarkText) + [ex: &fltr[]=wmt||||||||] + where: + is the text to use as a watermark, + is the font size (1-5 for built-in font, or point + size for TrueType fonts), + is the alignment (one of BR, BL, TR, TL, C, R, L, + T, B, * where B=bottom, T=top, L=left, R=right, + C=centre, *=tile), + is the hex color of the text + is the filename of the TTF file (optional, if + omitted a built-in font will be used) + is opacity from 0 to 100, + is the edge (and inter-tile) margin in percent + is the angle + (thanks mailmmjaeger*com) + - 'flip' [ex: &fltr[]=flip|x or &fltr[]=flip|y] + flip image on X or Y axis + (thanks mailmmjaeger*com) + - 'elip' [ex: &fltr[]=elip] + similar to rounded corners but more extreme + (thanks mailmmjaeger*com) + - 'mask' [ex: &fltr[]=mask|filename.png] + greyscale values of mask are applied as the alpha + channel to the main image. White is opaque, black + is transparent. + - 'bvl' (BeVeL) [ex: &fltr[]=bvl|||] + where is the bevel width, is the hex color + for the top and left shading, is the hex color + for the bottom and right shading + (thanks mailmmjaeger*com) + - 'fram' (FRAMe) draws a frame, similar to border but + more configurable (thanks mailmmjaeger*com) + [ex: &fltr[]=fram|||||] + where is the width of the main border, is + the width of each side of the bevel part, is the + hex color of the main border, is the highlight + bevel color, is the shadow bevel color + - 'drop' (DROP shadow) + [ex: &fltr[]=drop||||] + where is distance from image to shadow, is + width of shadow fade (not yet implemented), is + the hex color of the shadow, and is the angle of + the shadow (default=225) + - 'ric' (Rounded Image Corners) + [ex: &fltr[]=ric||] + where is the horizontal corner radius, + is the vertical corner radius + * Split out filter functions into phpthumb.filters.php + * 'usa','usr','ust' parameters have been removed and + replaced with the 'fltr' call (see above) + * 'wmf','wma','wmp','wmm' parameters have been removed + and replaced with the 'fltr' call (see above) + * 'brx','bry','bw' parameters have been removed + and replaced with the 'fltr' call (see above) + * 'bw=0' to force aspect ratio has been replaced by + 'far=1' (force aspect ratio) + * Filters that produce transparent sections (such as + Rounded Corners, Ellipse, Mask, Rotate) are now output + as 32-bit/alpha PNG, or flattened with "bg" background + color for JPEG/GIF output (thanks mailmmjaeger*com) + * Added 'zc' (Zoom Crop) parameter + (thanks arcookegmail*com, mailmmjaeger*com, + pl16056macnews*de, kezzasmusers*sourceforge*net, etc) + * AutoRotate now can use EXIF orientation tag ('ar=x') + * Added 'ttf_directory' configuration parameter for + TrueType watermarks (thanks mailmmjaeger*com) + * Added "Last-Modified" header to cache portion of + phpThumb.php which should allow better user-side + caching of thumbnails. (thanks dereknetsimple*net) + * Added 'cache_disable_warning' configuration which will + cause an error image to be displayed if the cache + directory isn't configured, unless explicitly disabled + * Added 'nooffsitelink_enabled' configuration which + prevents linking to thumbnails on your server from + another domain. Defaults to watermaking linked images + with text warning message. + (thanks anteabstraktmedia*com) + * Added 'error_image_width' & 'error_image_height' + config variables (thanks mailmmjaeger*com) + * Rounded image corners now requires GD v2.0.1 and PHP + v4.3.2. Corners are transparent (for PNG output) and + antialiased. + * Rotate by arbitary angle ('ra') now has a transparent + background for PNG output + * Cached filenames now have an additional component for + applied filters + * Cached filenames now have an additional component for + HTTP referer, but only if the refering domain does not + match the domain of the server (designed to prevent + imaged linked from offsite with error message being + cached the same as the local cached version) + * Added setSourceImageResource() to allow use of an + existing GD image resource for thumbnailing + (thanks dangonmad*co*uk) + * Now including phpThumb.demo.demo1.php (main demo page) + and phpThumb.demo.demo2.php (configurable demo page) + in the phpThumb() distribution + (thanks mailmmjaeger*com) + * Added many more debugging/tracing message points + * Added set_time_limit(30) to phpThumb.php + * Bugfix: ImageMagick not used if `which convert` points + to a link and not a file (thanks bkainersgmail*com) + * Bugfix: 'bgt' parameter was sometimes misspelled 'bct' + * Bugfix: 'wmm' couldn't be set to zero + * Bugfix: 'wmm' parameter was only applied to top/left of + image + * Bugfix: auto-detection of document_root failed on + Windows (thanks xbartvhotmail*com) + * Bugfix: phpThumbDebug could be bypassed if EXIF + thumbnail present (thanks olgradincheckfree*com) + * Bugfix: cache file wasn't being written if EXIF data + was used directly (thanks olgradincheckfree*com) + * Bugfix: phpThumb.demo.showpic.php was broken by popup + blockers for images larger than the screen. + (thanks mailmmjaeger*com) + +v1.4.11 - October 11, 2004 + * Changed sx/sy/sw/sh parameters to allow decimal values + (>0 but <1) to represent percent of source image + (thanks mordordefault*co*yu) + * Added config_error_silent_die_on_error for no-output + die on fatal errors (thanks johannesformformat*se) + * Added auto-detection of probable 'document_root' if + that key is not available in $_SERVER + * Bugfix: Check `which convert` failing with error + message (thanks chadchadshome*com) + * Bugfix: Image cropping to invalid areas outside source + image caused text output (thanks mordordefault*co*yu) + +v1.4.10 - August 22, 2004 + * Bugfix: cached files not written in most cases + (thanks kizercourtkizer*com, snuffinbox*ru) + * Bugfix: ApacheLookupURIarray() crashes in CGI mode + (thanks hanskrentelyahoo*de) + * Bugfix: phpthumb_bmpfile2gd() was broken + (thanks imindlace*net) + +v1.4.9 - August 9, 2004 + * Bugfix: changed destination filename in RenderToFile() + (thanks alextkwalla*com) + * Bugfix: problems with HTTP image source when called as + an object (thanks alextkwalla*com) + +v1.4.8 - August 4, 2004 + * $this->error has changed to $this->errors and is now + an array of strings (instead of a single string) + * A lot more error conditions (invalid cache directory, + etc) are now reported in $this->errors + (thanks aidan*slingsbylineone*net) + * Removed all define(CONSTANT) in the phpThumb() + constructor - you can now access: + - PHPTHUMB_VERSION == $this->phpthumb_version; + - PHPTHUMB_OSSLASH == $this->osslash; + - PHPTHUMB_ISWINDOWS == $this->iswindows; + * Bugfix: Error message from apache_lookup_uri() failing + under Apache2 now reported cleanly + (thanks derbaffyahoo*com) + * Bugfix: missing phpthumb_functions:: class name for + ImageTypeToMIMEtype() call in ExtractEXIFgetImageSize() + (thanks aidan*slingsbylineone*net) + * Bugfix: ImageTypeToMIMEtype() was broken for PHP older + than v4.3.0 (thanks georg*schreiberbatch-pc*es) + * Bugfix: RenderToFile() now returns false if it fails + (thanks phpthumbsendthemtomir*com) + * Bugfix: Corrupt JPEG/PNG/GIF files that failed + ImageCreateFrom*() were not being passed to ImageMagick + for fallback, nor passed through unmodified if IM was + unavailable or failed (thanks r*chongmogenic*net) + * Bugfix: Improved backtick safe-mode limit detection + (thanks 1adamcarrington*com) + * Bugfix: EXIF thumbnails were being used as source when + they should not be (thanks aidan*slingsbylineone*net) + * Bugfix: Cached files were not being created or used + properly (thanks aidan*slingsbylineone*net) + * Bugfix: max_source_pixels not set correct on some PHP + versions (thanks derbaffyahoo*com) + * Bugfix: 'down' parameter ignored for unprocessed and + cached files (thanks aidan*slingsbylineone*net) + +v1.4.7 - July 27, 2004 + * Included a modified version of "module.graphic.bmp.php" + from getID3() [http://getid3.sourceforge.net] as + "phpthumb.bmp.php" for BMP reading support without + ImageMagick. It works, but it's *very* slow, especially + for large images (as in 640x480 or larger). + * Added check to prevent error messages when shell_exec + is disabled (thanks webmasterneester*com) + +v1.4.6 - July 22, 2004 + * Added new section to phpthumb.config.php where you can + easily specify defaults for any parameter you can set + in the URL. Normally URL parameters override these + default values, unless you set + $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE to false + * Renamed phpthumb.config.php to phpThumb.config.php + since it's part of phpThumb.php, not part of + phpthumb.class.php (change of case only, will not + affect Windows servers, but will affect *nix) + * Changed cached filename of rawImageData-source images + from urlencode('') to md5(rawImageData). This should + make caching thumbnails from non-file sources more + reliable. + * Added ImageMagick debugging information + * Removed unneccesary default values from cached + filenames. This may invalidate some previously cached + files. phpthumb.demo.cacheconvert.php has been updated + to handle v1.4.1-1.4.5 => v1.4.6+ cache filenames. + * Bugfix: Cached filename did not have file-modified + datestamp when used as implmented in phpThumb.php + * Bugfix: RenderToFile() now accepts relative filenames + (thanks aidan*slingsbylineone*net) + * Bugfix: AllowOutputEnlargment setting was ignored when + falling back to ImageMagick + * Bugfix: IgnoreAspectRatio setting was ignored when + falling back to ImageMagick + * Bugfix: config_temp_directory was ignored in gd_info() + in PHP < v4.3.0 when phpinfo() returns no GD + information (due to safe mode restrictions) + (thanks mimyrtekmyrtek*com) + +v1.4.5 - June 28, 2004 + * Added new parameter 'down' where you can specify a + filename and OutputThumbnail() will cause the file + to be downloaded rather than displayed in the browser. + Demo images on silisoftware.com/scripts/phpThumb/demo/ + can all be downloaded to show off this feature. + (thanks stuartscrumpyahoo*co*uk) + * Added ability to remove old files from cache directory + based on last-access time and/or number of cached files + and/or total size of cached files + (thanks jrmhaigyahoo*co*uk) + * Added public CleanUpCacheDirectory() for cache cleaning + (see above) if you need to call it manually + * Included new file phpThumb.demo.cacheconvert.php to + convert old-style cache names to the current (and + hopefully last!) standard naming convention. + (thanks joshgtwcny*rr*com) + * Added configuration value 'document_root' for rare case + when $_SERVER['DOCUMENT_ROOT'] return incorrect value + (thanks joshgtwcny*rr*com) + * Now tries to create thumbnail with ImageMagick if + ImageCreateFromJPEG etc fails, before falling back to + outputting unmodified source data. + * Bugfix: HTTP image sources were broken + (thanks fritz*weisshartt-online*de) + * Bugfix: ImageMagick callout wasn't being used if EXIF + thumbnail was available + (thanks joshgtwcny*rr*com) + * Bugfix: HTTP src with space in filename was broken + (thanks drrhodes360*com) + * Bugfix: version_compare_replacement() was broken for + PHP v4.1.0+ + +v1.4.4 - June 8, 2004 + * Bugfix: network-share (Windows) source filenames were + not possible. Now works, but you must use the network + name and not a mapped drive name, for example: + \\othercomputer\file.jpg - good + \\192.168.2.1\file.jpg - good + z:\file.jpg - won't work + This is a PHP limitation (see www.php.net/file-exists) + Note: you may want to use "/" slashes instead of "\" if + you have magic_quotes_gpc enabled to avoid stripslashes + problems. + (thanks drrhodes360*com) + * Bugfix: missing "phpthumb_functions::" in + ImageCreateFromStringReplacement() + (thanks zapletalsoftwaremedia*cz) + +v1.4.3 - May 25, 2004 + * Added new configuration variable 'config_temp_directory' + to allow you to specify a writable directory name for + temp files if you do not have access to the system temp + directory on your server (Safe Mode restrictions etc) + (thanks nickregenmag*com) + * Added new configuration variable + 'config_error_die_on_error' which can be set to false if + you want to retrieve the error message without having it + dumped as an image - the error message is now available + in $phpThumb->error + * Images are passed through directly with no processing + and no caching if no parameters are passed to alter the + image (resize, crop, sharpening, etc) + (thanks nchmurausers*sourceforge*net) + * Added new configuration variable 'config_disable_debug' + which disabled phpThumbDebug from working if you have + security concerns about the displayed information + * Bugfix: Added detection at the top of phpThumb.php for + no-GD errors to avoid parse errors later in the code + (thanks nickregenmag*com) + * Bugfix: RoundedImageCorners() had some off-by-1 errors + (thanks ola*thunberghome*se) + +v1.4.2 - May 10, 2004 + * Added IE-compatability mode for transparent corners + (set 'bct=256') + * Bugfix: version_compare_replacement() was broken in PHP + older than 4.1.0 + (thanks nickregenmag*com) + +v1.4.1.1 - May 9, 2004 + * Bugfix: Removed ImageTrueColorToPalette hack. + See http://bugs.php.net/bug.php?id=28341 + * Bugfix: 'maxb' option for PNG/GIF output incorrect + bit depth under some circumstances + +v1.4.1 - May 9, 2004 + * Added 'maxb' (MAXimum Bytes) option to auto-set the + output image quality (JPEG) or bit depth (PNG/GIF) so + that the output thumbnail is less than 'maxb' bytes + (thanks e_bellehotmail*com) + * Added 'bgt' parameter to make rounded corners from + 'brx'/'bry' option transparent when used with PNG + output. Note: PHP/GD appears buggy at this time, so this + option must force output to 256-color mode for this + to work. The feature will be updated when a non-broken + version of PHP/GD is released. + (thanks javierircorion*net) + * Bugfix: Caching was broken + (thanks mikegdaymate*nl, jurewiczgo3*pl) + +v1.4.0 - April 30, 2004 + * Rewritten as a PHP class. Split into several files: + - phpthumb.class.php = most processing code + - phpthumb.functions.php = support functions + - phpthumb.readme.txt = usage instructions + - phpthumb.changelog.txt = this file + - phpthumb.config.php = configuration file + - phpthumb.gif.php = Non-GD GIF reading support + - phpthumb.unsharp.php = Unsharp Masking support + - phpThumb.php = demo script that works + exactly as previous versions; this is a drop-in + replacement for existing phpThumb() installations + - phpThumb.demo.showpic.php = demo script that auto- + resizes a popup window to the size of the image + shown. Useful if you want popup images but do not + know the large image size beforehand + * Added optional call-out to ImageMagick (if avaible) if + source image is larger than PHP memory restrictions + allow. ImageMagick installation should be auto-detected + under *nix, but you should configure 'imagemagick_path' + for use under Windows. + * 'max_source_pixels' is now auto-calculated from PHP + configuration settings. Due to various server-level + restrictions that may override PHP settings this + calculated value may not always be correct, and you may + have to specify the value manually. + * Added rounded-corner border option. You must specify + both 'brx' (horizontal radius) and 'bry' (vertical + radius) as well as 'bw' (border width). If 'bw' is + greater than zero, the image will be shrunk to fit + inside the border with a margin of background color. + If 'bw' is zero, the corners of the image will be + cut off and filled with background color. + (thanks javierircorion*net) + * Minor speed improvement for unsharp masking + +v1.3.7 - March 28, 2004 + * Bugfix: GD version detection was broken on PHP <4.3.0 + on servers where phpinfo() was disabled + (thanks javierircorion*net) + * Bugfix: Non-GD GIF support was broken on restricted + PHP configurations + (thanks javierircorion*net) + * Bugfix: phpThumb.gif.php output error messages if PHP + was running in Safe Mode + * Added 'iar' parameter (Ignore Aspect Ratio) to allow + non-proportional resizing (stretch image to fit). + You must specify 'h' and 'w' to use this option. + (thanks javierircorion*net) + +v1.3.6 - March 14, 2004 + * Bugfix: was broken when register_globals turned on + (thanks joshgtwcny*rr*com) + * Bugfix: Images with transparent backgrounds now have + the background color filled with the color specified + by the 'bg' parameter + * Bugfix: ImageCreateFromString() is broken in the + non-bundled GD. Added workaround, but please use + the bundled version of GD if possible + (thanks dnxbe*ch) + * Bugfix: EXIF thumbnail caching was broken + * Bugfix: EXIF thumbnail handling was broken for PHP + v4.2.x + (thanks smithk1shaw*ca) + * Bugfix: Image borders with GD2 were misaligned + * Bugfix: virtual paths/filenames like /~user/foo.jpg + should now work properly, if PHP is installed as an + Apache module (see www.php.net/apache-lookup-uri) + * Bugfix: contents of any non-image file could be + displayed (including PHP & HTML files) + (thanks arsyanarsyan*com) + * Added rotation parameters 'ra' and 'ar' + (thanks drrhodes360*com) + * Added $CONFIG['output_allow_enlarging'], defaulted + to false, to prevent smaller-than-max-size images + from being enlarged beyond their original size. If + you want to be able to enlarge images, set this to + false. Can be overridden with the 'aoe' parameter + (thanks dnxbe*ch) + * Changed all configuration variables to be under one + array named $CONFIG + * Moved color and font options for ErrorImage() to + $CONFIG variables + * Changed cached filename structure (again) to a more + flexible format that can handle future expansion + (old cached files are invalid and will be recreated) + * Added more debugging code to phpThumbDebug + +v1.3.5 - February 29, 2004 + * Added capability to use EXIF thumbnail that may be + embedded in source image (often is in digital camera + JPEGs) and source image dimensions are larger than + $config_max_source_pixels. This will overcome the + limitation where PHP runs out of memory processing + large images (usually >1600x1200). EXIF thumbnail + extraction requires PHP v4.2.0 or higher and EXIF + support compiled into PHP (or php_exif extension) + * Eliminated intermediate read-file-to-memory stage if + image is created from local file. Should allow + larger images to be processed without running out of + memory. + * Added optional 'goto' parameter to be used with the + 'file' parameter, where 'goto' is a URL that is + redirected to after image is rendered to file + (thanks wimblewebdonors*com) + * Added optional 'xto' parameter that will bypass all + processing and just return the embedded EXIF + thumbnail, if available. + * Added error-handling if ImageTypes() is unavailable + +v1.3.4 - February 15, 2004 + * Custom error image option (&err=img.jpg) which can + also be set as $config_error_message_image_default + (thanks carl4thstar*net) + * &f=text will now output plain-text error messages + * ErrorImage() now used for anti-hotlink messages (if + $config_nohotlink_erase_image is true) + +v1.3.3 - February 5, 2004 + * Bugfix: Added stripslashes() to filenames if + magic_quotes_gpc is enabled + (thanks arsyanarsyan*com) + * Output can now be rendered to a file only (not to + browser) specified by the 'file' parameter + (thanks arsyanarsyan*com) + * JPEG quality now has a maximum of 95%, as specified + in the GD documentation + +v1.3.2.1 - February 3, 2004 + * Bugfix: gd_version() was broken for GD v2.0+ + * Bugfix: removed debugging code + +v1.3.2 - February 3, 2004 + * Bugfix: when borders are enabled, portait images + with no width constraint, or landscape images with + no height constraint were smaller than neccesary by + double the border width + (thanks jjjxs4all*nl) + * Added unsharp mask option thanks to Torstein Hnsi: + http://www.vikjavev.com/hovudsida/umtestside.php + Note: requires GD v2.x to function + (thanks jjjxs4all*nl) + * Updated cache filenames to reflect new parameters, + this means old cached files will need to be deleted + (or not, they just will never get called again) and + new cached versions will be created. + * Added caching to gd_info() calls for minor speedup + +v1.3.1 - February 2, 2004 + * Added optional border (width and color configurable) + (thanks arsyanarsyan*com) + * Added option to create fixed-dimension thumbnails + regardless of source aspect ration. Set the 'bw' + (BorderWidth) parameter (even to 0) and this will be + enabled. Outside the actual image will be filled + with 'bg' color (default FFFFFF) + (thanks arsyanarsyan*com) + +v1.3.0 - January 27, 2004 + * Added watermarking option to overlay thumbnails with + a semi-transparent watermark image (copied from a + seperate source watermark image) + (thanks arsyanarsyan*com) + * Added option for absolute filenames (on both Windows + and *nix) outside the DOCUMENT_ROOT directory + * Added debug output dump for diagnosing problems) + +v1.2.8 - January 19, 2004 + * added ability to specify relative pathnames as well + as absolute pathnames (pathname is relative to the + location of phpThumb.php if the passed source does + not begin with "/" + +v1.2.7 - January 7, 2004 + * Added patch to allow use of PHP older than 4.1.0 + (or GD without PNG support) for non-GD GIF support + (thanks hostwebserverhotmail*com) + +v1.2.6 - January 4, 2004 + * Added patch to allow use of PHP older than 4.1.0 + (without the superglobals arrays) + +v1.2.5 - December 26, 2003 + * Added configuration options for default output image + format and max width/height + +v1.2.4 - December 20, 2003 + * Bugfix: temp directory for non-native GD support not + always returning valid directory + * Caching feature reintroduced (see configuration) + +v1.2.3 - December 19, 2003 + * Added anti-hotlink code so the thumbnail script on + one domain cannot be used by another domain. The + list of allowed domains defaults to the current + domain but is configurable below as + $config_nohotlink_valid_domains. The message, text + size, colors and whether to blank the image or not + are also configurable + * Bugfix: URL image sources were not able to use the + non-GD GIF-reading functions + +v1.2.2 - December 17, 2003 + * Added option to use http:// URL as image source + +v1.2.1 - December 11, 2003 + * Added option to get source data from a database + rather than a physical file + * Bugfix: resize not proportional when wide image + limited more by max height than max width + Thanks mathias_strassergmx*net + * Removed caching code + +v1.2.0 - December 10, 2003 + * Added GIF support for versions of GD that do not + have built-in GIF support (v1.6.x) via the "GIF + Util" class by Fabien Ezber (www.yamasoft.com) + GD's built-in GIF-reading functions are faster, and + are present in PHP v4.3.0 or newer, but all versions + of GD can display resized GIF thumbnails now. + +v1.1.2 - October 26, 2003 + * check for source image existance to prevent text + error messages + * if GD not available, a GIF saying "no GD" is shown + instead of showing the original image + * Cache feature introduced + +v1.1.1 - September 28, 2003 + * better resize code by sfisher10cox*net + +v1.1.0 - September 1, 2003 + * initial public release + * thumbnails can now be larger than source image + * graphical error messages + +v1.0.0 - January 7, 2002 + * initial private release diff --git a/common/phpThumb/docs/phpthumb.faq.txt b/common/phpThumb/docs/phpthumb.faq.txt new file mode 100644 index 0000000..9d5f5c1 --- /dev/null +++ b/common/phpThumb/docs/phpthumb.faq.txt @@ -0,0 +1,313 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// Frequently Asked Questions (FAQ) about phpThumb() // +// /// +////////////////////////////////////////////////////////////// + + +Q: My question isn't answered here and I can't find any + forums, how do I get support? +A: Please email me directly at info@silisoftware.com with + any questions, suggestions, donations, etc. + + +Q: I think I found a bug, what's the first thing I should do? +A: Please make sure you're using the latest version. There's + a good chance I may have already fixed the bug, so please + make sure you can reproduce it with the latest version + before reporting the bug. + + +Q: phpThumb doesn't work as expected, and it may be a server + configuration issue -- how do I check? +A: Please run /demo/demo.check.php to find out how your server + matches up with the recommended configuration and for + suggestions on what to change for improved performance. + + +Q: What is the GPL? Can I use this for commercial sites? +A: See the GPL FAQ: http://www.gnu.org/licenses/gpl-faq.html + In general, if you just want to call phpThumb.php in the + standard manner + then there is no problem, you're free to do this no matter + if you site is commercial or not, or what license your code + is released under. + If you're calling phpThumb() as an object then you will + probably run into license issues, so consult the above FAQ + and the GPL itself. + No matter if you use phpThumb() commercially or not, no + payment is required. However, donations are always welcome + and can be made at http://phpthumb.sourceforge.net + + +Q: Some images generate thumbnails, but some fail (the original + non-resized image is output instead). +A: Your PHP installation does not have a high enough memory_limit + and ImageMagick is not installed on the server. The PHP memory + required is 5 times the number of pixels in the image. + For example: + 640x480x5 = 1.5MB + 1600x1200x5 = 9.2MB + You can adjust the PHP memory limit in php.ini (if you have + permission on your server to do so), or (better yet) install + ImageMagick on the server and that will bypass the memory limit + issue. If you can't do either of the above, you can resize the + images manually (with your favourite image editor) to a size + that your memory_limit setting can handle, and/or you can + re-save the images with an image editor that can embed an EXIF + thumbnail (Photoshop for example) which phpThumb can use as an + image source (lower image quality, but perhaps better than + nothing). + + +Q: I'm getting is this error message: + Failed: RenderToFile() failed because + !is_resource($this->gdimg_output) +A: You missed the call to GenerateThumbnail() before + RenderToFile() or OutputThumbnail. + See /demo/phpThumb.demo.object.php for an example. + + +Q: I'm trying to save a phpThumb-generated image in Internet + Explorer and it saves in BMP format, why? +A: This is not phpThumb's fault, it is an IE issue: + http://support.microsoft.com/default.aspx?scid=kb;en-us;810978 + http://support.microsoft.com/default.aspx?scid=kb;en-us;260650 + + +Q: PNG images with transparent areas show up with gray background + in the areas that are supposed to be transparent. +A: Internet Explorer has had a broken PNG alpha-channel display + implementation for a decade, so it may never get fixed. Other + major browsers generally handle alpha-transparent PNGs fine. + See http://www.silisoftware.com/png_transparency/ + For an alpha-channel PNG display in IE hack, see this page: + http://www.koivi.com/ie-png-transparency/ + + +Q: I'm getting " does not exist" when I know the + file does exist +A: Check that these two values are present and properly + configured in phpThumb.config.php (introduced in v1.6.0): + $PHPTHUMB_CONFIG['allow_src_above_docroot'] (default=false) + $PHPTHUMB_CONFIG['allow_src_above_phpthumb'] (default=true) + If your images are outside DOCUMENT_ROOT then you will have + to configure 'allow_src_above_docroot' to true. + Make sure whatever user the webserver is running as has read + permission to the file/directory you're reading from + + +Q: Should I use phpThumb.php, or use phpThumb() as an object? +A: phpThumb.php is easier to use (less coding) for basic uses. + phpThumb.php handles all caching; your own object will need + to have its own caching code. If you just want to display a + thumbnailed version of an existing image, use phpThumb.php + If you want to render one (or more) thumbnails to static + files (during upload, for example), that's an appropriate + use for the object mode. Also, phpThumb.config.php is only + used by phpThumb.php, so if you instantiate your own object + you need to manually set all configuration options because + phpThumb.config.php has NO effect. So, to repeat: + **always use phpThumb.php unless you NEED to have an object** + + +Q: The first time I go to a page which contains thumbnails I + don't actually see the thumbnail, I just get a browser image + placeholder (or no image). As soon as I hit refresh, all the + thumbnail images pop into place really fast. +A: You can try and see if it works better with + $PHPTHUMB_CONFIG['cache_force_passthru'] = false; + but typically the default setting works better. + This is something of an unresolved issue on some servers, + where for whatever reason I haven't (yet?) been able to + figure out a setting that always works the first time. If the + above config setting doesn't help, you might be stuck with + having to manually or automagically pre-cache thumbnails as + they're created. Please email info@silisoftware.com if you + have a better solution... + + +Q: Are there any front-end GUI interfaces to phpThumb()? +A: See /demo/readme.demo.txt + + +Q: Are there / have there been any security issues in phpThumb? +A: http://secunia.com/product/5199/ + + +Q: Why can't Flash work with images output from phpThumb()? +A: Flash doesn't like progressive JPEG. Set: + $PHPTHUMB_CONFIG['output_interlace'] = false; + + +Q: Image quality is not very good - why? +A: If you're using GD v1.x, no way around it. Upgrade to GD v2.x + + +Q: Image quality is very bad, very pixelated -- why? +A: You may be trying to resize images larger than the available + PHP memory, so phpThumb is simply extracting and using the + EXIF thumbnail as the image source, which is usually about + 160x120 (so if you resize it to 640x480 it will look very bad). + To calculate the required size for memory_limit in php.ini, + calculate the number of pixels in the image and multiply by 5: + For example, 1600x1200 = 1600 * 1200 * 5 = 9600000 = 10M + Easy solution: install ImageMagick + + +Q: Can I save the generated thumbnail to a file? +A: Yes, there are several ways to do so; the best way is to call + phpThumb as an object and call RenderToFile() to save the + thumbnail to whatever filename you want. + See /demo/phpThumb.demo.object.php for an example. + The other way is to use the 'file' parameter (see + /docs/phpthumb.readme.txt) but this parameter is deprecated + and does not work in phpThumb v1.7.5 and newer. + + +Q: "Off-server thumbnailing is not allowed" -- how do I enable it? +A: By default, phpThumb() only makes thumbnails for the same + domain that it is running on. To allow it to make thumbnails + for a limited number of other domains, add them + (in phpThumb.config.php) like this: + $PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array( + @$_SERVER['HTTP_HOST'], 'example.com', 'www.example.com', + 'subdomain.example.net', 'example.org'); + To disable off-server thumbnail blocking, just set: + $PHPTHUMB_CONFIG['nohotlink_enabled'] = false; + + +Q: Is it possible to set the parameters (like w/h/fltr[]) in + the config, so that they can't be changed over the URL? +A: Take a look at $PHPTHUMB_DEFAULTS at the bottom of + phpThumb.config.php You'll want to set + $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE = false + possibly also + $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = true + You may also want to investigate + $PHPTHUMB_CONFIG['high_security_enabled'] = true + (see the example at the bottom of phpThumb.config.php + for how to call images in HighSecurity mode) + + +Q: Is there a way to use phpThumb() object to create thumbnails + without the parameters in the URL showing the location of + the image etc? +A: There is a demo in /demo/phpThumb.demo.object.php. You could + modify this into your own file, but there still remains the + problem of passing parameters to the file, whether it's + phpThumb.php or your own instantiation of a phpThumb() object. + I would suggest is putting as many of the common parameters + into phpThumb.config.php as possible under $PHPTHUMB_DEFAULTS, + so you then don't have to pass them for each image. If you + don't want people modifying the parameters, turn on + $PHPTHUMB_CONFIG['high_security_enabled'] and set a password + (you'll need to generate the tags with phpThumbURL() + provided at the bottom of phpThumb.config.php). If you don't + want people accessing your source images at all, you can + place them outside DOCUMENT_ROOT on your server (as long as + phpThumb/PHP has read access to the directory). The other + option is to put your source images in a MySQL database + and set $PHPTHUMB_CONFIG['mysql_query'] and related + parameters in phpThumb.config.php to pull your source images + from the database. That way it's impossible to retrieve the + images except through phpThumb.php, and if high_security is + enabled, then nobody can modify the parameters to view + anything except what you want to show. So, yes, it's possible + to use your own object, but it's probably better to use + phpThumb.php if possible -- one notable issue is that + phpThumb.php handles all the caching, so you're on your own + to deal with that if you create your own object. + + +Q: How do I write the output thumbnail back to a database instead + of outputting to the browser or a file? +A: See /demo/phpThumb.demo.object.php Basically you need to call + $this->GenerateThumbnail() then $this->RenderOutput() and then + the output raw image data is found in $this->outputImageData + + +Q: phpThumb runs slowly, as if the images aren't cached, when I use HTTP source + images (not on my server). How can I make it go faster? +A: $PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; + // if true, remote source images will not be checked for modification date and + // cached image will be used if available, even if source image is changed or removed + + +Q: What does the "cache_default_only_suffix" configuration option do? +A: Cache files are normally created with big ugly names like + "phpThumb_cache_www.example.com_src1a482c2c760463795ff18faf073b389f_par3e099041c2f4a73041a7f5d7e7fc481a_dat1119952152.jpeg" + but if cache_default_only_suffix is enabled, cache filenames are simplified to + "pic_thumb.jpg" (for example). The problem is that only one version of that + thumbnail is possible, and you can never call it again with a different size, + or different filters, etc. Generally you don't want that enabled, but it's + there because some people asked for it. + + +Q: Why is the visual size of rotated images smaller than the unrotated images? +A: phpThumb fits the rotated image into the 'w' and 'h' dimensions. + Try not specifying a 'w' parameter: phpThumb.php?src=file.png&ra=15 + That should leave the image the apparent same size as the unrotated image + (in actual fact the canvas size is enlarged to fit the rotated image in it). + + +Q: phpThumb.demo.check.php says Safe Mode is off for Master but on for Local, + and I checked php.ini and it's already set off. How do I disable safe mode? +A: Your PHP was probably installed as an Apache module. If so, you have to set + php_admin_value safe_mode "Off" + in your domain settings (usually between tags in httpd.conf). + Then you have to restart Apache. + + +Q: How can I purge cached files when I delete the source image? +A: You can either let phpThumb's built-in cache purging features (see phpThumb.config.php) + take effect, or you can manually walk through your source images to delete and find + the matching cache files and delete them: + if ($dh = opendir($sourcedir)) { + while ($file = readddir($dh)) { + if ($file == $WhatIwantToDelete) { + $md5 = md5_file($sourcedir.'/'.$file); + unlink($phpthumb_cache_dir.'/phpThumb_cache_www.example.com_src'.$md5.'*.*'); + } + } + closedir($dh); + } + + +Q: Can I make thumbnails from a PDF? +A: Yes, as long as you have both ImageMagick and GhostScript + installed. The AFPL version of GhostScript seems to work + better than the GNU version (at least for me it does). + http://www.imagemagick.org + http://www.cs.wisc.edu/~ghost/ + You may want to use the "sfn" (Source Frame Number) + parameter of phpThumb to specify which page to thumbnail. + + +Q: Can I make a thumbnail of a webpage? +A: Possibly, but it's not easy. Theoretically, if you have + html2ps, GhostScript and ImageMagick all installed it should + be possible, but I have not tested that. Other projects that + attempt to generate thumbnails from webpages include: + http://www.boutell.com/webthumb/ + + +Q: phpThumb is the best software in the world, how can I donate? +A: There's a handy "Support this project" button at the top of + http://phpthumb.sourceforge.net which will take you through + the process (and give SourceForge a ~5% cut), or if you prefer + you can send PayPal donations directly to info@silisoftware.com + + +Q: What is the proper name for this script/program/library? +A: The official name is "phpThumb()" but it may be written + as simply "phpThumb" in short form (or where parentheses + are not permitted), or "phpthumb" in case-insensitive + environments. The following is a non-exhaustive sample of + unacceptable forms: PHPthumb; phpThumbs; phpthump; + phpthumbnailer; phpThumbnail; PHP Thumb; Phpthumb; etc. + + diff --git a/common/phpThumb/docs/phpthumb.license.txt b/common/phpThumb/docs/phpthumb.license.txt new file mode 100644 index 0000000..339b705 --- /dev/null +++ b/common/phpThumb/docs/phpthumb.license.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/common/phpThumb/docs/phpthumb.readme.txt b/common/phpThumb/docs/phpthumb.readme.txt new file mode 100644 index 0000000..27ca93d --- /dev/null +++ b/common/phpThumb/docs/phpthumb.readme.txt @@ -0,0 +1,590 @@ +////////////////////////////////////////////////////////////// +/// phpThumb() by James Heinrich // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// This code is released under the GNU GPL: // +// http://www.gnu.org/copyleft/gpl.html // +// // +// +-----------------------------------------------+ // +// | phpThumb() is free to use according to the | // +// | terms of the GPL. Donations also gratefully | // +// | GPL FAQ: http://gnu.org/licenses/gpl-faq.html | // +// | | // +// | Donations are gratefully accepted from happy | // +// | users :) See http://phpthumb.sourceforge.net | // +// | | // +// | If you like phpThumb(), please consider | // +// | writing a review at HotScripts.com: | // +// | http://www.hotscripts.com/Detailed/25654.html | // +// | | // +// | If you do use this code somewhere, send me | // +// | an email and tell me how/where you used it. | // +// +-----------------------------------------------+ // +// /// +////////////////////////////////////////////////////////////// + +============ +Description: +============ + +phpThumb() uses the GD library to create thumbnails from +images (GIF, PNG or JPEG) on the fly. The output size is +configurable (can be larger or smaller than the source), +and the source may be the entire image or only a portion +of the original image. True color and resampling is used +if GD v2.0+ is available, otherwise low-color and simple +resizing is used. Source image can be a physical file on +the server or can be retrieved from a database. GIFs are +supported on all versions of GD even if GD does not have +native GIF support thanks to the GIFutil class by Fabien +Ezber. AntiHotlinking feature prevents other people from +using your server to resize their thumbnails, or link to +your images from another server. The cache feature +reduces server load. + + +======== +Support: +======== + +First, read this file. +Then read phpthumb.faq.txt +Then run /demo/phpThumb.demo.check.php +If you still think it's a bug, email info@silisoftware.com + + +====== +Usage: +====== + +Call phpThumb() just like you would a normal image. +Examples: + + +See the "demo" link on http://phpthumb.sourceforge.net +for more usage examples). Parameters that can be passed +are listed below under "URL Parameters". + +NOTE: It's recommended you use the local image filename +wherever possible (rather than http://) because performance +is much better, less (or no) use of temp files, and the +last-modified check for cached files doesn't work for +remote files. + +To access files over a LAN with Windows share names you +must use the network name (or IP) and not a mapped drive +name, for example: + //othercomputer/file.jpg - good + //192.168.2.1/file.jpg - good + z:/file.jpg - won't work +This is a PHP limitation (see www.php.net/file-exists) +Note: you may want to use "/" slashes instead of "\" if +you have magic_quotes_gpc enabled to avoid stripslashes +problems, although either slash should work if +magic_quotes_gpc is disabled + + +================================ +Alternate PATH_INFO-style Usage: +================================ + +phpThumb.php can also be called by passing parameters not +after the usual "?" but like this: + phpThumb.php/=;x; +For example: + phpThumb.php/100;pic.jpg + phpThumb.php/100;images/pic.jpg + phpThumb.php/100;/images/pic.jpg + phpThumb.php/100x200;pic.jpg + phpThumb.php/x200;pic.jpg + phpThumb.php/f=jpeg;q=50;100x200;pic.jpg + phpThumb.php/fltr[]=usm;100;pic.jpg + + must be the last item. Dimensions must be the second- +last item. As many key/value pairs for parameters can be +passed before those last two items, with each pair joined by +equals ("=") and seperated by semicolon (";") + + +============================================== +Calling as an object (not using phpThumb.php): +============================================== + +NOTE: most people don't need to and should not do this. +If you just want to display resized images, please just +use phpThumb.php, not the object mode. To render output +to one (or more) files instead of the browser, you should +skip phpThumb.php and instantiate your own object. Please +take a look at /demo/phpThumb.demo.object.php for details. + +Note: phpThumb.php is where the caching code is located, if + you instantiate your own phpThumb() object that code is + bypassed and it's up to you to handle the reading and + writing of cached files. + + +============== +Configuration: +============== + +There are some configuration options you may (but are +not required to) change. Most configuration options can +be set when you call phpThumb() - see list below), but +default configuration options (such as cache directory) +are in phpThumb.config.php - this is the only file you +should ever modify. + +The configuration file is distributed as +phpThumb.config.php.default to prevent accidental +overwriting of old configuration settings. Please +migrate your old settings to the new file (if upgrading), +or delete your old config and rename the default to +phpThumb.config.php + + +The amount of memory required for phpThumb depends on +several factors: the dimensions of the source image, +the dimensions of the output image, whether unsharp +masking is applied, whether watermarks are applied, etc. +The auto-detection of memory limits works as a general +"safe" value. You may be able to exceed the auto value +by a small or large amount, depending on whether you +apply watermarks and/or sharpening, and the output size +of your thumbnails. I do not currently have a reliable +formula for calculating such things, but I will attempt +to craft one for future versions of phpThumb(). Until +then, set "max_source_pixels" in phpThumb.config.php to a +value that works well for you (or leave it alone if the +defaults give you no problems). + +The configuration options you should maybe modify are: +* cache_directory - thumbnailing is slow and processor- + intensive. Enabling caching will dramatically speed + up future thumbnail serving +* max_source_pixels - This should be auto-detected, but + if auto-detection fails and you get an invalid image + from large source images, set this to about 20% of + your available PHP memory limit. +* imagemagick_path - If the source image is larger than + max_source_pixels allows, but ImageMagick is available + phpThumb() will use it to generate the thumbnail. + + +/////////////////////////////////////////////////////////// +Note: High-Security mode is recommended enabled if possible. + Set $PHPTHUMB_CONFIG['high_security_enabled'] in + phpThumb.config.php to enable it. Each call to phpThumb + needs to be made through the function supplied at the + bottom of phpThumb.config.php which create the hash: + require_once('phpThumb.config.php'); + echo ''; +/////////////////////////////////////////////////////////// + + +=============== +URL Parameters: +=============== + + src = filename of source image + new = create new image, not thumbnail of existing image. + Requires "w" and "h" parameters set. + [ex: &new=FF0000|75] - red background, 75% opacity + Set to hex color string of background. Opacity is + optional (defaults to 100% opaque). + w = max width of output thumbnail in pixels + h = max height of output thumbnail in pixels + wp = max width for portrait images + hp = max height for portrait images + wl = max width for landscape images + hl = max height for landscape images + ws = max width for square images + hs = max height for square images + f = output image format ("jpeg", "png", or "gif") + q = JPEG compression (1=worst, 95=best, 75=default) + sx = left side of source rectangle (default = 0) + (values 0 < sx < 1 represent percentage) + sy = top side of source rectangle (default = 0) + (values 0 < sy < 1 represent percentage) + sw = width of source rectangle (default = fullwidth) + (values 0 < sw < 1 represent percentage) + sh = height of source rectangle (default = fullheight) + (values 0 < sh < 1 represent percentage) + zc = zoom-crop. Will auto-crop off the larger dimension + so that the image will fill the smaller dimension + (requires both "w" and "h"). Set "zc=1" to enable. + (overrides both "iar" and "far") + bg = background hex color (default = FFFFFF) + bc = border hex color (default = 000000) +fltr = filter system. Call as an array as follows: + - "brit" (Brightness) [ex: &fltr[]=brit|] + where is the amount +/- to adjust brightness + (range -255 to 255) + Availble in PHP5 with bundled GD only. + - "cont" (Constrast) [ex: &fltr[]=cont|] + where is the amount +/- to adjust contrast + (range -255 to 255) + Availble in PHP5 with bundled GD only. + - "gam" (Gamma Correction) [ex: &fltr[]=gam|] + where can be a number >0 to 10+ (default 1.0) + Must be >0 (zero gives no effect). There is no max, + although beyond 10 is pretty useless. Negative + numbers actually do something, maybe not quite the + desired effect, but interesting nonetheless. + - "sat" (SATuration) [ex: &fltr[]=sat|] + where is a number between zero (no change) + and -100 (complete desaturation = grayscale), or it + can be any positive number for increased saturation. + - "ds" (DeSaturate) [ex: &fltr[]=ds|] + is an alias for "sat" except values are inverted + (positive values remove color, negative values boost + saturation) + - "gray" (Grayscale) [ex: &fltr[]=gray] + remove all color from image, make it grayscale + - "th" (Threshold) [ex: &fltr[]=th|] + makes image greyscale, then sets all pixels brighter + than (range 0-255) to white, and all pixels + darker than to black + - "rcd" (Reduce Color Depth) [ex: &fltr[]=rcd||] + where is the number of colors (2-256) you want + in the output image, and is "1" for dithering + (deault) or "0" for no dithering + - "clr" (Colorize) [ex: &fltr[]=clr||] + where is a number between 0 and 100 for the + amount of colorization, and is the hex color + to colorize to. + - "sep" (Sepia) [ex: &fltr[]=sep||] + where is a number between 0 and 100 for the + amount of colorization (default=50), and is + the hex color to colorize to (default=A28065). + Note: this behaves differently when applied by + ImageMagick, in which case 80 is default, and lower + values give brighter/yellower images and higher + values give darker/bluer images + - "usm" (UnSharpMask) [ex: &fltr[]=usm|||] + where is the amount (default = 80), is the + radius (default = 0.5), is the threshold + (default = 3). + - "blur" (Blur) [ex: &fltr[]=blur|] + where (0 < < 25) (default = 1) + - "gblr" (Gaussian Blur) [ex: &fltr[]=gblr] + Availble in PHP5 with bundled GD only. + - "sblr" (Selective Blur) [ex: &fltr[]=gblr] + Availble in PHP5 with bundled GD only. + - "smth" (Smooth) [ex: &fltr[]=smth|] + where is the weighting value for the matrix + (range -10 to 10, default 6) + Availble in PHP5 with bundled GD only. + - "lvl" (Levels) + [ex: &fltr[]=lvl||| + where can be one of 'r', 'g', 'b', 'a' (for + Red, Green, Blue, Alpha respectively), or '*' for all + RGB channels (default) based on grayscale average. + ImageMagick methods can support multiple channels + (eg "lvl|rg|3") but internal methods cannot (they will + use first character of channel string as channel) + can be one of: + 0=Internal RGB; + 1=Internal Grayscale; + 2=ImageMagick Contrast-Stretch (default) + 3=ImageMagick Normalize (may appear over-saturated) + is how much of brightest/darkest pixels + will be clipped in percent (default = 0.1%) + Using default parameters (&fltr[]=lvl) is similar to + Auto Contrast in Adobe Photoshop. + - "wb" (White Balance) [ex: &fltr[]=wb|] + where is the target hex color to white balance + on, this color is what "should be" white, or light + gray. The filter attempts to maintain brightness so + any gray color can theoretically be used. If is + omitted the filter guesses based on brightest pixels + in each of RGB + OR can be the percent of white clipping used + to calculate auto-white-balance (default = 0.1%) + NOTE: "wb" in default settings already gives an effect + similar to "lvl", there is usually no need to use "lvl" + if "wb" is already used. + - "hist" (Histogram) + [ex: &fltr[]=hist||||||||] + Where is the color band(s) to display, from back + to front (one or more of "rgba*" for Red Green Blue + Alpha and Grayscale respectively); + is a semicolon-seperated list of hex colors to + use for each graph band (defaults to FF0000, 00FF00, + 0000FF, 999999, FFFFFF respectively); + and are the width and height of the overlaid + histogram in pixels, or if <= 1 then percentage of + source image width/height; + is the alignment (same as for "wmi" and "wmt"); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + and are the edge margin in pixels (or percent + if 0 < (x|y) < 1) + - "over" (OVERlay/underlay image) overlays an image on + the thumbnail, or overlays the thumbnail on another + image (to create a picture frame for example) + [ex: &fltr[]=over||||] + where is the image filename; is "0" (default) + for overlay the image on top of the thumbnail or "1" + for overlay the thumbnail on top of the image; is + the margin - can be absolute pixels, or if < 1 is a + percentage of the thumbnail size [must be < 0.5] + (default is 0 for overlay and 10% for underlay); + is opacity (0 = transparent, 100 = opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + (thanks raynerapegmail*com, shabazz3msu*edu) + - "wmi" (WaterMarkImage) + [ex: &fltr[]=wmi|||||] where + is the filename of the image to overlay; + is the alignment (one of BR, BL, TR, TL, C, + R, L, T, B, *) where B=bottom, T=top, L=left, + R=right, C=centre, *=tile); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + and are the edge (and inter-tile) margin in + pixels (or percent if 0 < (x|y) < 1) + - "wmt" (WaterMarkText) + [ex: &fltr[]=wmt|||||||||||] + where: + is the text to use as a watermark; + URLencoded Unicode HTMLentities must be used for + characters beyond chr(127). For example, the + "eighth note" character (U+266A) is represented + as "♪" and then urlencoded to "%26%239834%3B" + Any instance of metacharacters will be replaced + with their calculated value. Currently supported: + ^Fb = source image filesize in bytes + ^Fk = source image filesize in kilobytes + ^Fm = source image filesize in megabytes + ^X = source image width in pixels + ^Y = source image height in pixels + ^x = thumbnail width in pixels + ^y = thumbnail height in pixels + ^^ = the character ^ + is the font size (1-5 for built-in font, or point + size for TrueType fonts); + is the alignment (one of BR, BL, TR, TL, C, R, L, + T, B, * where B=bottom, T=top, L=left, R=right, + C=centre, *=tile); + is the hex color of the text; + is the filename of the TTF file (optional, if + omitted a built-in font will be used); + is opacity from 0 (transparent) to 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the edge (and inter-tile) margin in percent; + is the angle + is the hex color of the background; + is background opacity from 0 (transparent) to + 100 (opaque) + (requires PHP v4.3.2, otherwise 100% opaque); + is the direction(s) in which the background is + extended (either 'x' or 'y' (or both, but both + will obscure entire image)) + Note: works with TTF fonts only, not built-in + - "flip" [ex: &fltr[]=flip|x or &fltr[]=flip|y] + flip image on X or Y axis + - "ric" [ex: &fltr[]=ric||] + rounds off the corners of the image (to transparent + for PNG output), where is the horizontal radius + of the curve and is the vertical radius + - "elip" [ex: &fltr[]=elip] + similar to rounded corners but more extreme + - "mask" [ex: &fltr[]=mask|filename.png] + greyscale values of mask are applied as the alpha + channel to the main image. White is opaque, black + is transparent. + - "bvl" (BeVeL) [ex: &fltr[]=bvl|||] + where is the bevel width, is the hex color + for the top and left shading, is the hex color + for the bottom and right shading + - "bord" (BORDer) [ex: &fltr[]=bord|||| + where is the width in pixels, and are + horizontal and vertical radii for rounded corners, + and is the hex color of the border + - "fram" (FRAMe) draws a frame, similar to "bord" but + more configurable + [ex: &fltr[]=fram|||||] + where is the width of the main border, is + the width of each side of the bevel part, is the + hex color of the main border, is the highlight + bevel color, is the shadow bevel color + - "drop" (DROP shadow) + [ex: &fltr[]=drop||||] + where is distance from image to shadow, is + width of shadow fade (not yet implemented), is + the hex color of the shadow, and is the angle of + the shadow (default=225) + - "crop" (CROP image) + [ex: &fltr[]=crop||||] + where is the number of pixels to crop from the left + side of the resized image; , , are for right, + top and bottom respectively. Where (0 < x < 1) the + value will be used as a percentage of width/height. + Left and top crops take precedence over right and + bottom values. Cropping will be limited such that at + least 1 pixel of width and height always remains. + - "rot" (ROTate) + [ex: &fltr[]=rot||] + where is the rotation angle in degrees; is the + background hex color. Similar to regular "ra" parameter + but is applied in filter order after regular processing + so you can rotate output of other filters. +md5s = MD5 hash of the source image -- if this parameter is + passed with the hash of the source image then the + source image is not checked for existance or + modification and the cached file is used (if + available). If 'md5s' is passed an empty string then + phpThumb.php dies and outputs the correct MD5 hash + value. This parameter is the single-file equivalent + of 'cache_source_filemtime_ignore_*' configuration + paramters + xto = EXIF Thumbnail Only - set to only extract EXIF + thumbnail and not do any additional processing + ra = Rotate by Angle: angle of rotation in degrees + positive = counterclockwise, negative = clockwise + ar = Auto Rotate: set to "x" to use EXIF orientation + stored by camera. Can also be set to "l" or "L" + for landscape, or "p" or "P" for portrait. "l" + and "P" rotate the image clockwise, "L" and "p" + rotate the image counter-clockwise. + sfn = Source Frame Number - use this frame/page number for + multi-frame/multi-page source images (GIF, TIFF, etc) + aoe = Output Allow Enlarging - override the setting for + $CONFIG['output_allow_enlarging'] (1=on, 0=off) + ("far" and "iar" both override this and allow output + larger than input) + iar = Ignore Aspect Ratio - disable proportional resizing + and stretch image to fit "h" & "w" (which must both + be set). (1=on, 0=off) (overrides "far") + far = Force Aspect Ratio - image will be created at size + specified by "w" and "h" (which must both be set). + Alignment: L=left,R=right,T=top,B=bottom,C=center + BL,BR,TL,TR use the appropriate direction if the + image is landscape or portrait. + dpi = Dots Per Inch - input DPI setting when importing from + vector image format such as PDF, WMF, etc + sia = Save Image As - default filename to save generated + image as. Specify the base filename, the extension + (eg: ".png") will be automatically added +maxb = MAXimum Byte size - output quality is auto-set to + fit thumbnail into "maxb" bytes (compression + quality is adjusted for JPEG, bit depth is adjusted + for PNG and GIF) +down = filename to save image to. If this is set the + browser will prompt to save to this filename rather + than display the image + +// Deprecated: +file = if set then thumbnail will be rendered to this + filename, not output and not cached. + (Deprecated. Disabled by default since v1.6.0, + unavailable in v1.7.5 and later. You should + instantiate your own object instead) +goto = URL to redirect to after rendering image to file + * Must begin with "http://" + * Requires file parameter set + (Deprecated. Disabled by default since v1.6.0, + unavailable in v1.7.5 and later. You should + instantiate your own object instead) + err = custom error image filename instead of showing + error messages (for use on production sites) + (Deprecated. Disabled by default since v1.6.0, + unavailable in v1.7.5 and later. You should + instantiate your own object instead) + + +============== +General Notes: +============== + +* Always use the local image filename wherever possible + rather than a full http:// URL because performance is + much better, less (or no) use of temp files, and the + last-modified check for cached files doesn't work for + remote files. For example: + good: phpThumb.php?src=/images/nicepic.jpg + bad: phpThumb.php?src=/home/httpd/example/images/nicepic.jpg + worse: phpThumb.php?src=http://example.com/images/nicepic.jpg + +* Thumbnails will be scaled proportionately to fit in a + box of at most (width * height) pixels + (unless "iar" is set) + +* Thumbnail caching for URL or database sources requires + an absolute directory name for $config_cache_directory + Physical file cached thumbnails will be recreated if + the source file changes, but remote/database files + cannot (modification time isn't readily available) + +* If you need a GUI interface to phpThumb(), or for a user + to specify crop settings, or something like that please + see the list of known programs in /demo/readme.demos.txt + +* Cropping images can be specified with either exact pixel + values for sx/sy/sw/sh parameters, or if those are set + to a value >0 and <1 then these are interpreted as a + percentage of the source image width/height. For example, + to crop 25% off all sides, you would specify parameters: + phpThumb.php?src=pic.jpg&sx=.25&sy=.25&sw=.5&sh=.5 + +* phpThumb() may have tempfile access issues on servers + where Safe Mode is enabled, specificly when accessing + a file over HTTP, or when a non-bundled version of GD + is in use. Specifying "config_temp_directory" may help + +* Properly resolving /~user/ style filenames requires + apache_lookup_uri(), which is missing or broken in + Apache2, or if PHP is not installed as an Apache module. + phpThumb() does try and work around this if it is + unavailble, but you may have to specify a full filename + for "src" if you encounter problems. + +* phpThumb() should work with PHP v4.0.6+, but seems to + have a few quirks before v4.1.0 + EXIF thumbnail extraction requires PHP v4.2.0+ + Image rotation requires PHP v4.3.0+. There have been + reports of problems with PHP older than v4.3.3 + Some image filters require PHP v5.0.0+ + Run /demo/phpThumb.demo.check.php to examine your server + +* phpThumb() works better and faster when ImageMagick is + available. Most functions will work with only GD2, but + speed is much faster with ImageMagick, and much larger + images can be processed with ImageMagick than GD. + +* phpThumb() works with GD v1.x, but works better with + GD v2.0+ because of the true-color image support + and ImageCopyResampled(). Also, there appears to be a + bug in ImageCopyResized() which is used with GD v1.x + where the bottom and/or right line of pixels is set + to the background color (due to a rounding error?) + NOTE: Please use the bundled version of GD if at all + possible (with PHP v4.3.0+) because the non-bundled + version has bugs which may cause PHP to crash: + * http://bugs.php.net/bug.php?id=21518 + * http://bugs.php.net/bug.php?id=24174 + phpThumb() has a workaround for the above bug but + there may be other bugs, and the workaround is slow. + Alpha transparent output requires GD >= 2.0.1 and + PHP >= 4.3.2 + Most (if not all) filters require GD v2.x to function + at all. But many filters can be handled by ImageMagick + instead of GD. + +* Filters handled by ImageMagick or GD: + - brit;cont;ds;sat;gray;clr;sep;gam;neg;th;rcd;flip;edge; + emb;lvl;blur;gblr;usm;wb; +* Filters handled only by ImageMagick: + - none yet +* Filters handled only by GD + PHP5: + - sblr;mean;smth; +* Filters handled only by GD2: + - bvl;wmi;wmt;over;hist;fram;drop;mask;elip;ric;bord; + + +=============== +Thanks & Links: +=============== + +* Original image used in phpThumb logo provided by + Mark James: http://www.famfamfam.com/lab/icons/ diff --git a/common/phpThumb/fonts/a.ttf b/common/phpThumb/fonts/a.ttf new file mode 100644 index 0000000..ba71390 Binary files /dev/null and b/common/phpThumb/fonts/a.ttf differ diff --git a/common/phpThumb/fonts/b.ttf b/common/phpThumb/fonts/b.ttf new file mode 100644 index 0000000..7ac9b02 Binary files /dev/null and b/common/phpThumb/fonts/b.ttf differ diff --git a/common/phpThumb/fonts/readme.txt b/common/phpThumb/fonts/readme.txt new file mode 100644 index 0000000..04935c2 --- /dev/null +++ b/common/phpThumb/fonts/readme.txt @@ -0,0 +1,5 @@ +This is the default location for TTF fonts. + +You can safely delete or ignore this directory if you're not using +TTF fonts for text watermarks. You can also specify an alternate +directory in phpThumb.config.php \ No newline at end of file diff --git a/common/phpThumb/images/readme.txt b/common/phpThumb/images/readme.txt new file mode 100644 index 0000000..c1c10ff --- /dev/null +++ b/common/phpThumb/images/readme.txt @@ -0,0 +1,4 @@ +If you're looking for the demo images, they can be downloaded from +the bottom of the phpThumb demo page on SourceForge: + +http://phpthumb.sourceforge.net/demo/demo/phpThumb.demo.demo.php \ No newline at end of file diff --git a/common/phpThumb/index.php b/common/phpThumb/index.php new file mode 100644 index 0000000..b5f98c0 --- /dev/null +++ b/common/phpThumb/index.php @@ -0,0 +1,3 @@ + \ No newline at end of file diff --git a/common/phpThumb/phpThumb.config.php b/common/phpThumb/phpThumb.config.php new file mode 100644 index 0000000..1e24fa5 --- /dev/null +++ b/common/phpThumb/phpThumb.config.php @@ -0,0 +1,256 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.readme.txt for usage instructions // +// NOTE: THIS FILE HAS NO EFFECT IN OBJECT MODE! // +// THIS CONFIG FILE ONLY APPLIES TO phpThumb.php // +// /// +////////////////////////////////////////////////////////////// + +ob_start(); +if (!file_exists(dirname(__FILE__).'/phpthumb.functions.php') || !include_once(dirname(__FILE__).'/phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once(phpthumb.functions.php) - realpath="'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'"'); +} +ob_end_clean(); + +// START USER CONFIGURATION SECTION: + +// * DocumentRoot configuration +// phpThumb() depends on $_SERVER['DOCUMENT_ROOT'] to resolve path/filenames. This value is usually correct, +// but has been known to be broken on some servers. This value allows you to override the default value. +// Do not modify from the auto-detect default value unless you are having problems. +//$PHPTHUMB_CONFIG['document_root'] = '/home/httpd/httpdocs'; +//$PHPTHUMB_CONFIG['document_root'] = 'c:\\webroot\\example.com\\www'; +//$PHPTHUMB_CONFIG['document_root'] = $_SERVER['DOCUMENT_ROOT']; +//$PHPTHUMB_CONFIG['document_root'] = realpath((@$_SERVER['DOCUMENT_ROOT'] && file_exists(@$_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF'])) ? $_SERVER['DOCUMENT_ROOT'] : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', realpath('.')))); +$PHPTHUMB_CONFIG['document_root'] = realpath((getenv('DOCUMENT_ROOT') && ereg('^'.preg_quote(realpath(getenv('DOCUMENT_ROOT'))), realpath(__FILE__))) ? getenv('DOCUMENT_ROOT') : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__)))); + +// * Cache directory configuration (choose only one of these - leave the other lines commented-out): +// Note: this directory must be writable (usually chmod 777 is neccesary) for caching to work. +// If the directory is not writable no error will be generated but caching will be disabled. +$PHPTHUMB_CONFIG['cache_directory'] = dirname(__FILE__).'/cache/'; // set the cache directory relative to the phpThumb() installation +//$PHPTHUMB_CONFIG['cache_directory'] = $PHPTHUMB_CONFIG['document_root'].'/phpthumb/cache/'; // set the cache directory to an absolute directory for all source images +//$PHPTHUMB_CONFIG['cache_directory'] = './cache/'; // set the cache directory relative to the source image - must start with '.' (will not work to cache URL- or database-sourced images, please use an absolute directory name) +//$PHPTHUMB_CONFIG['cache_directory'] = null; // disable thumbnail caching (not recommended) +//if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { +// $PHPTHUMB_CONFIG['cache_directory'] = dirname(__FILE__).'/cache/'; // set the cache directory to an absolute directory for all source images +//} else { +// $PHPTHUMB_CONFIG['cache_directory'] = '/tmp/persistent/phpthumb/cache/'; +//} + +$PHPTHUMB_CONFIG['cache_disable_warning'] = true; // If [cache_directory] is non-existant or not writable, and [cache_disable_warning] is false, an error image will be generated warning to either set the cache directory or disable the warning (to avoid people not knowing about the cache) + +$PHPTHUMB_CONFIG['cache_directory_depth'] = 4; // If this larger than zero, cache structure will be broken into a broad directory structure based on cache filename. For example "cache_src012345..." will be stored in "/0/01/012/0123/cache_src012345..." when (cache_directory_depth = 4) + + +// * Cache culling: phpThumb can automatically limit the contents of the cache directory +// based on last-access date and/or number of files and/or total filesize. + +//$PHPTHUMB_CONFIG['cache_maxage'] = null; // never delete cached thumbnails based on last-access time +$PHPTHUMB_CONFIG['cache_maxage'] = 86400 * 30; // delete cached thumbnails that haven't been accessed in more than [30 days] (value is maximum time since last access in seconds to avoid deletion) + +//$PHPTHUMB_CONFIG['cache_maxsize'] = null; // never delete cached thumbnails based on byte size of cache directory +$PHPTHUMB_CONFIG['cache_maxsize'] = 10 * 1024 * 1024; // delete least-recently-accessed cached thumbnails when more than [10MB] of cached files are present (value is maximum bytesize of all cached files) + +//$PHPTHUMB_CONFIG['cache_maxfiles'] = null; // never delete cached thumbnails based on number of cached files +$PHPTHUMB_CONFIG['cache_maxfiles'] = 200; // delete least-recently-accessed cached thumbnails when more than [200] cached files are present (value is maximum number of cached files to keep) + + +// * Source image cache configuration +$PHPTHUMB_CONFIG['cache_source_enabled'] = false; // if true, source images obtained via HTTP are cached to $PHPTHUMB_CONFIG['cache_source_directory'] +$PHPTHUMB_CONFIG['cache_source_directory'] = dirname(__FILE__).'/cache/source/'; // set the cache directory for unprocessed source images + +// * cache source modification date configuration +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_local'] = false; // if true, local source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; // if true, remote source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed. WARNING: cached performance MUCH slower if this is set to false. + + +// * Simplified cache filename configuration +// Instead of creating unique cache filenames for all parameter combinations, create "simple" cache files (eg: "pic_thumb.jpg") +// If cache_default_only_suffix is non-empty, GETstring parameters (except 'src') are ignored and only $PHPTHUMB_DEFAULTS +// parameters (set at the bottom of phpThumb.config.php) are used for processing. +// The '*' character MUST be used to represent the source image name +$PHPTHUMB_CONFIG['cache_default_only_suffix'] = ''; // cached in normal phpThumb manner +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = '*_thumb'; // cache 'pic.jpg' becomes 'pic_thumb.jpg' (or 'pic_thumb.png' if PNG output is selected, etc) +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = 'small-*'; // cache 'pic.jpg' becomes 'small-pic.jpg' (or 'small-pic.png' if PNG output is selected, etc) + +$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache_'.str_replace('www.', '', @$_SERVER['SERVER_NAME']); +//$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache'; // allow phpThumb to share 1 set of cached files even if accessed under different servername/domains on same server + +$PHPTHUMB_CONFIG['cache_force_passthru'] = true; // if true, cached image data will always be passed to browser; if false, HTTP redirect will be used instead + + + +// * Temp directory configuration +// phpThumb() may need to create temp files. Usually the system temp dir is writable and can be used. +// Leave this value as NULL in most cases. If you get errors about "failed to open for writing" +// you should change this to a full pathname to a directory you do have write access to. +//$PHPTHUMB_CONFIG['temp_directory'] = null; // attempt to auto-detect +//$PHPTHUMB_CONFIG['temp_directory'] = '/tmp/persistent/phpthumb/cache/'; // set to absolute path +$PHPTHUMB_CONFIG['temp_directory'] = $PHPTHUMB_CONFIG['cache_directory']; // set to same as cache directory + + +// NOTE: "max_source_pixels" only affects GD-resized thumbnails. If you have ImageMagick +// installed it will bypass most of these limits +// maximum number of pixels in source image to attempt to process entire image in GD mode. +// If this is zero then no limit on source image dimensions. +// If this is nonzero then this is the maximum number of pixels the source image +// can have to be processed normally, otherwise the embedded EXIF thumbnail will +// be used (if available) or an "image too large" notice will be displayed. +// This is to be used for large source images (> 1600x1200) and low PHP memory +// limits. If PHP runs out of memory the script will usually just die with no output. +// To calculate this number, multiply the dimensions of the largest image +// you can process with your memory limitation (e.g. 1600 * 1200 = 1920000) +// As a general guideline, this number will be about 20% of your PHP memory +// configuration, so 8M = 1,677,722; 16M = 3,355,443; 32M = 6,710,886; etc. +if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && !defined('memory_get_usage') && !@ini_get('memory_limit')) { + // memory_get_usage() will only be defined if your PHP is compiled with the --enable-memory-limit configuration option. + $PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit +} else { + // calculate default max_source_pixels as 1/6 of memory limit configuration + $PHPTHUMB_CONFIG['max_source_pixels'] = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 / 6); + //$PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 1920000; // allow 1600x1200 images (2Mpx), no larger (about 12MB memory required) + //$PHPTHUMB_CONFIG['max_source_pixels'] = 2795000; // 16MB memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 3871488; // allow 2272x1704 images (4Mpx), no larger (about 24MB memory required) +} + + +// ImageMagick configuration +$PHPTHUMB_CONFIG['prefer_imagemagick'] = true; // If true, use ImageMagick to resize thumbnails if possible, since it is usually faster than GD functions; if false only use ImageMagick if PHP memory limit is too low. +$PHPTHUMB_CONFIG['imagemagick_use_thumbnail'] = true; // If true, use ImageMagick's "-thumbnail" resizing parameter (if available) which removes extra non-image metadata (profiles, EXIF info, etc) resulting in much smaller filesize; if false, use "-resize" paramter which retains this info +if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + // Windows: set absolute pathname + $PHPTHUMB_CONFIG['imagemagick_path'] = 'C:/ImageMagick/convert.exe'; +} else { + // *nix: set absolute pathname to "convert", or leave as null if "convert" is in the path (location detected with `which`) + //$PHPTHUMB_CONFIG['imagemagick_path'] = '/usr/local/bin/convert'; + $PHPTHUMB_CONFIG['imagemagick_path'] = null; +} + + + +// * Default output configuration: +$PHPTHUMB_CONFIG['output_format'] = 'jpeg'; // default output format ('jpeg', 'png' or 'gif') - thumbnail will be output in this format (if available in your version of GD). This is always overridden by ?f=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxwidth'] = 0; // default maximum thumbnail width. If this is zero then default width is the width of the source image. This is always overridden by ?w=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxheight'] = 0; // default maximum thumbnail height. If this is zero then default height is the height of the source image. This is always overridden by ?h=___ GETstring parameter +$PHPTHUMB_CONFIG['output_interlace'] = true; // if true: interlaced output for GIF/PNG, progressive output for JPEG; if false: non-interlaced for GIF/PNG, baseline for JPEG. + +// * Error message configuration +$PHPTHUMB_CONFIG['error_image_width'] = 400; // default width for error images +$PHPTHUMB_CONFIG['error_image_height'] = 100; // default height for error images +$PHPTHUMB_CONFIG['error_message_image_default'] = ''; // Set this to the name of a generic error image (e.g. '/images/error.png') that you want displayed in place of any error message that may occur. This setting is overridden by the 'err' parameter, which does the same thing. +$PHPTHUMB_CONFIG['error_bgcolor'] = 'CCCCFF'; // background color of error message images +$PHPTHUMB_CONFIG['error_textcolor'] = 'FF0000'; // color of text in error messages +$PHPTHUMB_CONFIG['error_fontsize'] = 1; // size of text in error messages, from 1 (smallest) to 5 (largest) +$PHPTHUMB_CONFIG['error_die_on_error'] = true; // die with error message on any fatal error (recommended with standalone phpThumb.php) +$PHPTHUMB_CONFIG['error_silent_die_on_error'] = false; // simply die with no output of any kind on fatal errors (not recommended) +$PHPTHUMB_CONFIG['error_die_on_source_failure'] = true; // die with error message if source image cannot be processed by phpThumb() (usually because source image is corrupt in some way). If false the source image will be passed through unprocessed, if true (default) an error message will be displayed. + +// * Off-server Thumbnailing Configuration: +$PHPTHUMB_CONFIG['nohotlink_enabled'] = false; // If false will allow thumbnailing from any source domain +$PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. Note: domain only, do not include port numbers. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format "www.example.com" +$PHPTHUMB_CONFIG['nohotlink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nohotlink_text_message'] = 'Off-server thumbnailing is not allowed'; // text of error message + +// * Off-server Linking Configuration: +$PHPTHUMB_CONFIG['nooffsitelink_enabled'] = true; // If false will allow thumbnails to be linked to from any domain, if true only domains listed below in 'nooffsitelink_valid_domains' will be allowed. +$PHPTHUMB_CONFIG['nooffsitelink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' +$PHPTHUMB_CONFIG['nooffsitelink_require_refer'] = false; // If false will allow standalone calls to phpThumb(). If true then only requests with a $_SERVER['HTTP_REFERER'] value in 'nooffsitelink_valid_domains' are allowed. +$PHPTHUMB_CONFIG['nooffsitelink_erase_image'] = false; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nooffsitelink_watermark_src'] = '/demo/images/watermark.png'; // webroot-relative image to overlay on hotlinked images +$PHPTHUMB_CONFIG['nooffsitelink_text_message'] = 'Image taken from '.@$_SERVER['HTTP_HOST']; // text of error message (used if [nooffsitelink_watermark_src] is not a valid image) + + +// * Border & Background default colors +$PHPTHUMB_CONFIG['border_hexcolor'] = '000000'; // Default border color - usual HTML-style hex color notation (overidden with 'bc' parameter) +$PHPTHUMB_CONFIG['background_hexcolor'] = 'FFFFFF'; // Default background color when thumbnail aspect ratio does not match fixed-dimension box - usual HTML-style hex color notation (overridden with 'bg' parameter) + +// * Watermark configuration +$PHPTHUMB_CONFIG['ttf_directory'] = dirname(__FILE__).'/fonts'; // Base directory for TTF font files +//$PHPTHUMB_CONFIG['ttf_directory'] = 'c:/windows/fonts'; + + +// * MySQL configuration +// You may want to pull data from a database rather than a physical file +// If so, modify the $PHPTHUMB_CONFIG['mysql_query'] line to suit your database structure +// Note: the data retrieved must be the actual binary data of the image, not a URL or filename + +$PHPTHUMB_CONFIG['mysql_query'] = ''; +//$PHPTHUMB_CONFIG['mysql_query'] = 'SELECT `picture` FROM `products` WHERE (`id` = \''.mysql_escape_string(@$_GET['id']).'\')'; + +// These 4 values must be modified if $PHPTHUMB_CONFIG['mysql_query'] is not empty, but may be ignored if $PHPTHUMB_CONFIG['mysql_query'] is blank. +$PHPTHUMB_CONFIG['mysql_hostname'] = 'localhost'; +$PHPTHUMB_CONFIG['mysql_username'] = ''; +$PHPTHUMB_CONFIG['mysql_password'] = ''; +$PHPTHUMB_CONFIG['mysql_database'] = ''; + + +// * Security configuration +$PHPTHUMB_CONFIG['high_security_enabled'] = false; // if enabled, requires 'high_security_password' set to at least 5 characters, and requires the use of phpThumbURL() function (at the bottom of phpThumb.config.php) to generate hashed URLs +$PHPTHUMB_CONFIG['high_security_password'] = ''; // required if 'high_security_enabled' is true, must be at least 5 characters long +$PHPTHUMB_CONFIG['disable_debug'] = false; // prevent phpThumb from displaying any information about your system. If true, phpThumbDebug and error messages will be disabled +$PHPTHUMB_CONFIG['allow_src_above_docroot'] = false; // if true, allow src to be anywhere in filesystem; if false (default) only allow src within document_root +$PHPTHUMB_CONFIG['allow_src_above_phpthumb'] = true; // if true (default), allow src to be anywhere in filesystem; if false only allow src within sub-directory of phpThumb installation +$PHPTHUMB_CONFIG['allow_parameter_file'] = false; // if true, allow use of 'file' parameter; if false (default) the 'file' parameter is disabled/ignored +$PHPTHUMB_CONFIG['allow_parameter_goto'] = false; // if true, allow use of 'goto' parameter; if false (default) the 'goto' parameter is disabled/ignored + + +// * HTTP UserAgent configuration +//$PHPTHUMB_CONFIG['http_user_agent'] = ''; // PHP default: none +//$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'; // Windows XP, Internet Explorer +$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; // Windows XP, Firefox + + +// * Compatability settings +$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] = false; // if true, $_SERVER[PATH_INFO] is not parsed. May be needed on some server configurations to allow normal behavior. +$PHPTHUMB_CONFIG['disable_imagecopyresampled'] = false; // if true, ImageCopyResampled is replaced with ImageCopyResampleBicubic. May be needed for buggy versions of PHP-GD. +$PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] = true; // if true, any image that can be parsed by GetImageSize() can be passed through; if false, only images that can be converted to GD by ImageCreateFrom(JPEG|GIF|PNG) functions are allowed + + +// * HTTP remote file opening settings +$PHPTHUMB_CONFIG['http_fopen_timeout'] = 10; // timeout (in seconds) for fopen / curl / fsockopen +$PHPTHUMB_CONFIG['http_follow_redirect'] = true; // if true (default), follow "302 Found" redirects to new URL; if false, return error message + + +// * Speed optimizations configuration +$PHPTHUMB_CONFIG['use_exif_thumbnail_for_speed'] = false; // If true, and EXIF thumbnail is available, and is larger or equal to output image dimensions, use EXIF thumbnail rather than actual source image for generating thumbnail. Benefit is only speed, avoiding resizing large image. +$PHPTHUMB_CONFIG['allow_local_http_src'] = true; // If true, 'src' parameter can be "http:///path/image.ext" instead of just "/path/image.ext"; if false then display warning message to encourage more efficient local-filename calling. + +// END USER CONFIGURATION SECTION + +/////////////////////////////////////////////////////////////////////////////// + +// START DEFAULT PARAMETERS SECTION +// If any parameters are constant across ALL images, you can set them here + +$PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE = true; // if true, any parameters in the URL will override the defaults set here; if false, any parameters set here cannot be overridden in the URL +$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = false; // if true, GETstring parameters will be ignored (except for 'src') and only below default parameters will be used; if false, both default and GETstring parameters will be used (depending on $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE). Will be auto-set true if !empty($PHPTHUMB_CONFIG['cache_default_only_suffix']) + +//$PHPTHUMB_DEFAULTS['w'] = 200; +//$PHPTHUMB_DEFAULTS['fltr'] = array('blur|10'); +//$PHPTHUMB_DEFAULTS['q'] = 90; + + +// END DEFAULT PARAMETERS SECTION + + + +/////////////////////////////////////////////////////////////////////////////// +// Function for generating hashed calls to phpThumb if 'high_security_enabled' +// example: +// require_once($_SERVER['DOCUMENT_ROOT'].'/phpThumb/phpThumb.config.php'); +// echo ''; + +function phpThumbURL($ParameterString) { + global $PHPTHUMB_CONFIG; + return str_replace(@$PHPTHUMB_CONFIG['document_root'], '', dirname(__FILE__)).DIRECTORY_SEPARATOR.'phpThumb.php?'.$ParameterString.'&hash='.md5($ParameterString.@$PHPTHUMB_CONFIG['high_security_password']); +} + +/////////////////////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/common/phpThumb/phpThumb.config.php.default b/common/phpThumb/phpThumb.config.php.default new file mode 100644 index 0000000..cd3c214 --- /dev/null +++ b/common/phpThumb/phpThumb.config.php.default @@ -0,0 +1,256 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.readme.txt for usage instructions // +// NOTE: THIS FILE HAS NO EFFECT IN OBJECT MODE! // +// THIS CONFIG FILE ONLY APPLIES TO phpThumb.php // +// /// +////////////////////////////////////////////////////////////// + +ob_start(); +if (!file_exists(dirname(__FILE__).'/phpthumb.functions.php') || !include_once(dirname(__FILE__).'/phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once(phpthumb.functions.php) - realpath="'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'"'); +} +ob_end_clean(); + +// START USER CONFIGURATION SECTION: + +// * DocumentRoot configuration +// phpThumb() depends on $_SERVER['DOCUMENT_ROOT'] to resolve path/filenames. This value is usually correct, +// but has been known to be broken on some servers. This value allows you to override the default value. +// Do not modify from the auto-detect default value unless you are having problems. +//$PHPTHUMB_CONFIG['document_root'] = '/home/httpd/httpdocs'; +//$PHPTHUMB_CONFIG['document_root'] = 'c:\\webroot\\example.com\\www'; +//$PHPTHUMB_CONFIG['document_root'] = $_SERVER['DOCUMENT_ROOT']; +//$PHPTHUMB_CONFIG['document_root'] = realpath((@$_SERVER['DOCUMENT_ROOT'] && file_exists(@$_SERVER['DOCUMENT_ROOT'].$_SERVER['PHP_SELF'])) ? $_SERVER['DOCUMENT_ROOT'] : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', realpath('.')))); +$PHPTHUMB_CONFIG['document_root'] = realpath((getenv('DOCUMENT_ROOT') && ereg('^'.preg_quote(realpath(getenv('DOCUMENT_ROOT'))), realpath(__FILE__))) ? getenv('DOCUMENT_ROOT') : str_replace(dirname(@$_SERVER['PHP_SELF']), '', str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__)))); + +// * Cache directory configuration (choose only one of these - leave the other lines commented-out): +// Note: this directory must be writable (usually chmod 777 is neccesary) for caching to work. +// If the directory is not writable no error will be generated but caching will be disabled. +$PHPTHUMB_CONFIG['cache_directory'] = dirname(__FILE__).'/cache/'; // set the cache directory relative to the phpThumb() installation +//$PHPTHUMB_CONFIG['cache_directory'] = $PHPTHUMB_CONFIG['document_root'].'/phpthumb/cache/'; // set the cache directory to an absolute directory for all source images +//$PHPTHUMB_CONFIG['cache_directory'] = './cache/'; // set the cache directory relative to the source image - must start with '.' (will not work to cache URL- or database-sourced images, please use an absolute directory name) +//$PHPTHUMB_CONFIG['cache_directory'] = null; // disable thumbnail caching (not recommended) +//if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { +// $PHPTHUMB_CONFIG['cache_directory'] = dirname(__FILE__).'/cache/'; // set the cache directory to an absolute directory for all source images +//} else { +// $PHPTHUMB_CONFIG['cache_directory'] = '/tmp/persistent/phpthumb/cache/'; +//} + +$PHPTHUMB_CONFIG['cache_disable_warning'] = true; // If [cache_directory] is non-existant or not writable, and [cache_disable_warning] is false, an error image will be generated warning to either set the cache directory or disable the warning (to avoid people not knowing about the cache) + +$PHPTHUMB_CONFIG['cache_directory_depth'] = 4; // If this larger than zero, cache structure will be broken into a broad directory structure based on cache filename. For example "cache_src012345..." will be stored in "/0/01/012/0123/cache_src012345..." when (cache_directory_depth = 4) + + +// * Cache culling: phpThumb can automatically limit the contents of the cache directory +// based on last-access date and/or number of files and/or total filesize. + +//$PHPTHUMB_CONFIG['cache_maxage'] = null; // never delete cached thumbnails based on last-access time +$PHPTHUMB_CONFIG['cache_maxage'] = 86400 * 30; // delete cached thumbnails that haven't been accessed in more than [30 days] (value is maximum time since last access in seconds to avoid deletion) + +//$PHPTHUMB_CONFIG['cache_maxsize'] = null; // never delete cached thumbnails based on byte size of cache directory +$PHPTHUMB_CONFIG['cache_maxsize'] = 10 * 1024 * 1024; // delete least-recently-accessed cached thumbnails when more than [10MB] of cached files are present (value is maximum bytesize of all cached files) + +//$PHPTHUMB_CONFIG['cache_maxfiles'] = null; // never delete cached thumbnails based on number of cached files +$PHPTHUMB_CONFIG['cache_maxfiles'] = 200; // delete least-recently-accessed cached thumbnails when more than [200] cached files are present (value is maximum number of cached files to keep) + + +// * Source image cache configuration +$PHPTHUMB_CONFIG['cache_source_enabled'] = false; // if true, source images obtained via HTTP are cached to $PHPTHUMB_CONFIG['cache_source_directory'] +$PHPTHUMB_CONFIG['cache_source_directory'] = dirname(__FILE__).'/cache/source/'; // set the cache directory for unprocessed source images + +// * cache source modification date configuration +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_local'] = false; // if true, local source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed +$PHPTHUMB_CONFIG['cache_source_filemtime_ignore_remote'] = true; // if true, remote source images will not be checked for modification date and cached image will be used if available, even if source image is changed or removed. WARNING: cached performance MUCH slower if this is set to false. + + +// * Simplified cache filename configuration +// Instead of creating unique cache filenames for all parameter combinations, create "simple" cache files (eg: "pic_thumb.jpg") +// If cache_default_only_suffix is non-empty, GETstring parameters (except 'src') are ignored and only $PHPTHUMB_DEFAULTS +// parameters (set at the bottom of phpThumb.config.php) are used for processing. +// The '*' character MUST be used to represent the source image name +$PHPTHUMB_CONFIG['cache_default_only_suffix'] = ''; // cached in normal phpThumb manner +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = '*_thumb'; // cache 'pic.jpg' becomes 'pic_thumb.jpg' (or 'pic_thumb.png' if PNG output is selected, etc) +//$PHPTHUMB_CONFIG['cache_default_only_suffix'] = 'small-*'; // cache 'pic.jpg' becomes 'small-pic.jpg' (or 'small-pic.png' if PNG output is selected, etc) + +$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache_'.str_replace('www.', '', @$_SERVER['SERVER_NAME']); +//$PHPTHUMB_CONFIG['cache_prefix'] = 'phpThumb_cache'; // allow phpThumb to share 1 set of cached files even if accessed under different servername/domains on same server + +$PHPTHUMB_CONFIG['cache_force_passthru'] = true; // if true, cached image data will always be passed to browser; if false, HTTP redirect will be used instead + + + +// * Temp directory configuration +// phpThumb() may need to create temp files. Usually the system temp dir is writable and can be used. +// Leave this value as NULL in most cases. If you get errors about "failed to open for writing" +// you should change this to a full pathname to a directory you do have write access to. +//$PHPTHUMB_CONFIG['temp_directory'] = null; // attempt to auto-detect +//$PHPTHUMB_CONFIG['temp_directory'] = '/tmp/persistent/phpthumb/cache/'; // set to absolute path +$PHPTHUMB_CONFIG['temp_directory'] = $PHPTHUMB_CONFIG['cache_directory']; // set to same as cache directory + + +// NOTE: "max_source_pixels" only affects GD-resized thumbnails. If you have ImageMagick +// installed it will bypass most of these limits +// maximum number of pixels in source image to attempt to process entire image in GD mode. +// If this is zero then no limit on source image dimensions. +// If this is nonzero then this is the maximum number of pixels the source image +// can have to be processed normally, otherwise the embedded EXIF thumbnail will +// be used (if available) or an "image too large" notice will be displayed. +// This is to be used for large source images (> 1600x1200) and low PHP memory +// limits. If PHP runs out of memory the script will usually just die with no output. +// To calculate this number, multiply the dimensions of the largest image +// you can process with your memory limitation (e.g. 1600 * 1200 = 1920000) +// As a general guideline, this number will be about 20% of your PHP memory +// configuration, so 8M = 1,677,722; 16M = 3,355,443; 32M = 6,710,886; etc. +if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && !defined('memory_get_usage') && !@ini_get('memory_limit')) { + // memory_get_usage() will only be defined if your PHP is compiled with the --enable-memory-limit configuration option. + $PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit +} else { + // calculate default max_source_pixels as 1/6 of memory limit configuration + $PHPTHUMB_CONFIG['max_source_pixels'] = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 / 6); + //$PHPTHUMB_CONFIG['max_source_pixels'] = 0; // no memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 1920000; // allow 1600x1200 images (2Mpx), no larger (about 12MB memory required) + //$PHPTHUMB_CONFIG['max_source_pixels'] = 2795000; // 16MB memory limit + //$PHPTHUMB_CONFIG['max_source_pixels'] = 3871488; // allow 2272x1704 images (4Mpx), no larger (about 24MB memory required) +} + + +// ImageMagick configuration +$PHPTHUMB_CONFIG['prefer_imagemagick'] = true; // If true, use ImageMagick to resize thumbnails if possible, since it is usually faster than GD functions; if false only use ImageMagick if PHP memory limit is too low. +$PHPTHUMB_CONFIG['imagemagick_use_thumbnail'] = true; // If true, use ImageMagick's "-thumbnail" resizing parameter (if available) which removes extra non-image metadata (profiles, EXIF info, etc) resulting in much smaller filesize; if false, use "-resize" paramter which retains this info +if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN') { + // Windows: set absolute pathname + $PHPTHUMB_CONFIG['imagemagick_path'] = 'C:/ImageMagick/convert.exe'; +} else { + // *nix: set absolute pathname to "convert", or leave as null if "convert" is in the path (location detected with `which`) + //$PHPTHUMB_CONFIG['imagemagick_path'] = '/usr/local/bin/convert'; + $PHPTHUMB_CONFIG['imagemagick_path'] = null; +} + + + +// * Default output configuration: +$PHPTHUMB_CONFIG['output_format'] = 'jpeg'; // default output format ('jpeg', 'png' or 'gif') - thumbnail will be output in this format (if available in your version of GD). This is always overridden by ?f=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxwidth'] = 0; // default maximum thumbnail width. If this is zero then default width is the width of the source image. This is always overridden by ?w=___ GETstring parameter +$PHPTHUMB_CONFIG['output_maxheight'] = 0; // default maximum thumbnail height. If this is zero then default height is the height of the source image. This is always overridden by ?h=___ GETstring parameter +$PHPTHUMB_CONFIG['output_interlace'] = true; // if true: interlaced output for GIF/PNG, progressive output for JPEG; if false: non-interlaced for GIF/PNG, baseline for JPEG. + +// * Error message configuration +$PHPTHUMB_CONFIG['error_image_width'] = 400; // default width for error images +$PHPTHUMB_CONFIG['error_image_height'] = 100; // default height for error images +$PHPTHUMB_CONFIG['error_message_image_default'] = ''; // Set this to the name of a generic error image (e.g. '/images/error.png') that you want displayed in place of any error message that may occur. This setting is overridden by the 'err' parameter, which does the same thing. +$PHPTHUMB_CONFIG['error_bgcolor'] = 'CCCCFF'; // background color of error message images +$PHPTHUMB_CONFIG['error_textcolor'] = 'FF0000'; // color of text in error messages +$PHPTHUMB_CONFIG['error_fontsize'] = 1; // size of text in error messages, from 1 (smallest) to 5 (largest) +$PHPTHUMB_CONFIG['error_die_on_error'] = true; // die with error message on any fatal error (recommended with standalone phpThumb.php) +$PHPTHUMB_CONFIG['error_silent_die_on_error'] = false; // simply die with no output of any kind on fatal errors (not recommended) +$PHPTHUMB_CONFIG['error_die_on_source_failure'] = true; // die with error message if source image cannot be processed by phpThumb() (usually because source image is corrupt in some way). If false the source image will be passed through unprocessed, if true (default) an error message will be displayed. + +// * Off-server Thumbnailing Configuration: +$PHPTHUMB_CONFIG['nohotlink_enabled'] = false; // If false will allow thumbnailing from any source domain +$PHPTHUMB_CONFIG['nohotlink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. Note: domain only, do not include port numbers. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format "www.example.com" +$PHPTHUMB_CONFIG['nohotlink_erase_image'] = true; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nohotlink_text_message'] = 'Off-server thumbnailing is not allowed'; // text of error message + +// * Off-server Linking Configuration: +$PHPTHUMB_CONFIG['nooffsitelink_enabled'] = true; // If false will allow thumbnails to be linked to from any domain, if true only domains listed below in 'nooffsitelink_valid_domains' will be allowed. +$PHPTHUMB_CONFIG['nooffsitelink_valid_domains'] = array(@$_SERVER['HTTP_HOST']); // This is the list of domains for which thumbnails are allowed to be created. The default value of the current domain should be fine in most cases, but if neccesary you can add more domains in here, in the format 'www.example.com' +$PHPTHUMB_CONFIG['nooffsitelink_require_refer'] = false; // If false will allow standalone calls to phpThumb(). If true then only requests with a $_SERVER['HTTP_REFERER'] value in 'nooffsitelink_valid_domains' are allowed. +$PHPTHUMB_CONFIG['nooffsitelink_erase_image'] = false; // if true thumbnail is covered up with $PHPTHUMB_CONFIG['nohotlink_fill_color'] before text is applied, if false text is written over top of thumbnail +$PHPTHUMB_CONFIG['nooffsitelink_watermark_src'] = '/demo/images/watermark.png'; // webroot-relative image to overlay on hotlinked images +$PHPTHUMB_CONFIG['nooffsitelink_text_message'] = 'Image taken from '.@$_SERVER['HTTP_HOST']; // text of error message (used if [nooffsitelink_watermark_src] is not a valid image) + + +// * Border & Background default colors +$PHPTHUMB_CONFIG['border_hexcolor'] = '000000'; // Default border color - usual HTML-style hex color notation (overidden with 'bc' parameter) +$PHPTHUMB_CONFIG['background_hexcolor'] = 'FFFFFF'; // Default background color when thumbnail aspect ratio does not match fixed-dimension box - usual HTML-style hex color notation (overridden with 'bg' parameter) + +// * Watermark configuration +$PHPTHUMB_CONFIG['ttf_directory'] = dirname(__FILE__).'/fonts'; // Base directory for TTF font files +//$PHPTHUMB_CONFIG['ttf_directory'] = 'c:/windows/fonts'; + + +// * MySQL configuration +// You may want to pull data from a database rather than a physical file +// If so, modify the $PHPTHUMB_CONFIG['mysql_query'] line to suit your database structure +// Note: the data retrieved must be the actual binary data of the image, not a URL or filename + +$PHPTHUMB_CONFIG['mysql_query'] = ''; +//$PHPTHUMB_CONFIG['mysql_query'] = 'SELECT `picture` FROM `products` WHERE (`id` = \''.mysql_escape_string(@$_GET['id']).'\')'; + +// These 4 values must be modified if $PHPTHUMB_CONFIG['mysql_query'] is not empty, but may be ignored if $PHPTHUMB_CONFIG['mysql_query'] is blank. +$PHPTHUMB_CONFIG['mysql_hostname'] = 'localhost'; +$PHPTHUMB_CONFIG['mysql_username'] = ''; +$PHPTHUMB_CONFIG['mysql_password'] = ''; +$PHPTHUMB_CONFIG['mysql_database'] = ''; + + +// * Security configuration +$PHPTHUMB_CONFIG['high_security_enabled'] = false; // if enabled, requires 'high_security_password' set to at least 5 characters, and requires the use of phpThumbURL() function (at the bottom of phpThumb.config.php) to generate hashed URLs +$PHPTHUMB_CONFIG['high_security_password'] = ''; // required if 'high_security_enabled' is true, must be at least 5 characters long +$PHPTHUMB_CONFIG['disable_debug'] = false; // prevent phpThumb from displaying any information about your system. If true, phpThumbDebug and error messages will be disabled +$PHPTHUMB_CONFIG['allow_src_above_docroot'] = false; // if true, allow src to be anywhere in filesystem; if false (default) only allow src within document_root +$PHPTHUMB_CONFIG['allow_src_above_phpthumb'] = true; // if true (default), allow src to be anywhere in filesystem; if false only allow src within sub-directory of phpThumb installation +$PHPTHUMB_CONFIG['allow_parameter_file'] = false; // if true, allow use of 'file' parameter; if false (default) the 'file' parameter is disabled/ignored +$PHPTHUMB_CONFIG['allow_parameter_goto'] = false; // if true, allow use of 'goto' parameter; if false (default) the 'goto' parameter is disabled/ignored + + +// * HTTP UserAgent configuration +//$PHPTHUMB_CONFIG['http_user_agent'] = ''; // PHP default: none +//$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)'; // Windows XP, Internet Explorer +$PHPTHUMB_CONFIG['http_user_agent'] = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; // Windows XP, Firefox + + +// * Compatability settings +$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] = false; // if true, $_SERVER[PATH_INFO] is not parsed. May be needed on some server configurations to allow normal behavior. +$PHPTHUMB_CONFIG['disable_imagecopyresampled'] = false; // if true, ImageCopyResampled is replaced with ImageCopyResampleBicubic. May be needed for buggy versions of PHP-GD. +$PHPTHUMB_CONFIG['disable_onlycreateable_passthru'] = true; // if true, any image that can be parsed by GetImageSize() can be passed through; if false, only images that can be converted to GD by ImageCreateFrom(JPEG|GIF|PNG) functions are allowed + + +// * HTTP remote file opening settings +$PHPTHUMB_CONFIG['http_fopen_timeout'] = 10; // timeout (in seconds) for fopen / curl / fsockopen +$PHPTHUMB_CONFIG['http_follow_redirect'] = true; // if true (default), follow "302 Found" redirects to new URL; if false, return error message + + +// * Speed optimizations configuration +$PHPTHUMB_CONFIG['use_exif_thumbnail_for_speed'] = false; // If true, and EXIF thumbnail is available, and is larger or equal to output image dimensions, use EXIF thumbnail rather than actual source image for generating thumbnail. Benefit is only speed, avoiding resizing large image. +$PHPTHUMB_CONFIG['allow_local_http_src'] = false; // If true, 'src' parameter can be "http:///path/image.ext" instead of just "/path/image.ext"; if false then display warning message to encourage more efficient local-filename calling. + +// END USER CONFIGURATION SECTION + +/////////////////////////////////////////////////////////////////////////////// + +// START DEFAULT PARAMETERS SECTION +// If any parameters are constant across ALL images, you can set them here + +$PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE = true; // if true, any parameters in the URL will override the defaults set here; if false, any parameters set here cannot be overridden in the URL +$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = false; // if true, GETstring parameters will be ignored (except for 'src') and only below default parameters will be used; if false, both default and GETstring parameters will be used (depending on $PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE). Will be auto-set true if !empty($PHPTHUMB_CONFIG['cache_default_only_suffix']) + +//$PHPTHUMB_DEFAULTS['w'] = 200; +//$PHPTHUMB_DEFAULTS['fltr'] = array('blur|10'); +//$PHPTHUMB_DEFAULTS['q'] = 90; + + +// END DEFAULT PARAMETERS SECTION + + + +/////////////////////////////////////////////////////////////////////////////// +// Function for generating hashed calls to phpThumb if 'high_security_enabled' +// example: +// require_once($_SERVER['DOCUMENT_ROOT'].'/phpThumb/phpThumb.config.php'); +// echo ''; + +function phpThumbURL($ParameterString) { + global $PHPTHUMB_CONFIG; + return str_replace(@$PHPTHUMB_CONFIG['document_root'], '', dirname(__FILE__)).DIRECTORY_SEPARATOR.'phpThumb.php?'.$ParameterString.'&hash='.md5($ParameterString.@$PHPTHUMB_CONFIG['high_security_password']); +} + +/////////////////////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/common/phpThumb/phpThumb.php b/common/phpThumb/phpThumb.php new file mode 100644 index 0000000..69d1011 --- /dev/null +++ b/common/phpThumb/phpThumb.php @@ -0,0 +1,591 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.changelog.txt for recent changes // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +error_reporting(E_ALL); +ini_set('display_errors', '1'); +if (!@ini_get('safe_mode')) { + set_time_limit(60); // shouldn't take nearly this long in most cases, but with many filter and/or a slow server... +} +ini_set('magic_quotes_runtime', '0'); +if (@ini_get('magic_quotes_runtime')) { + die('"magic_quotes_runtime" is set in php.ini, cannot run phpThumb with this enabled'); +} +$starttime = array_sum(explode(' ', microtime())); + +// this script relies on the superglobal arrays, fake it here for old PHP versions +if (phpversion() < '4.1.0') { + $_SERVER = $HTTP_SERVER_VARS; + $_GET = $HTTP_GET_VARS; +} + +// instantiate a new phpThumb() object +ob_start(); +if (!include_once(dirname(__FILE__).'/phpthumb.class.php')) { + ob_end_flush(); + die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.class.php').'")'); +} +ob_end_clean(); +$phpThumb = new phpThumb(); +$phpThumb->DebugTimingMessage('phpThumb.php start', __FILE__, __LINE__, $starttime); +$phpThumb->SetParameter('config_error_die_on_error', true); + +// phpThumbDebug[0] used to be here, but may reveal too much +// info when high_security_mode should be enabled (not set yet) + +if (file_exists(dirname(__FILE__).'/phpThumb.config.php')) { + ob_start(); + if (include_once(dirname(__FILE__).'/phpThumb.config.php')) { + // great + } else { + ob_end_flush(); + $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); + } + ob_end_clean(); +} elseif (file_exists(dirname(__FILE__).'/phpThumb.config.php.default')) { + $phpThumb->ErrorImage('Please rename "phpThumb.config.php.default" to "phpThumb.config.php"'); +} else { + $phpThumb->ErrorImage('failed to include_once('.dirname(__FILE__).'/phpThumb.config.php) - realpath="'.realpath(dirname(__FILE__).'/phpThumb.config.php').'"'); +} + +if (!@$PHPTHUMB_CONFIG['disable_pathinfo_parsing'] && (empty($_GET) || isset($_GET['phpThumbDebug'])) && !empty($_SERVER['PATH_INFO'])) { + $_SERVER['PHP_SELF'] = str_replace($_SERVER['PATH_INFO'], '', @$_SERVER['PHP_SELF']); + + $args = explode(';', substr($_SERVER['PATH_INFO'], 1)); + $phpThumb->DebugMessage('PATH_INFO.$args set to ('.implode(')(', $args).')', __FILE__, __LINE__); + if (!empty($args)) { + $_GET['src'] = @$args[count($args) - 1]; + if (eregi('^new\=([a-z0-9]+)', $_GET['src'], $matches)) { + unset($_GET['src']); + $_GET['new'] = $matches[1]; + } + } + if (eregi('^([0-9]*)x?([0-9]*)$', @$args[count($args) - 2], $matches)) { + $_GET['w'] = $matches[1]; + $_GET['h'] = $matches[2]; + $phpThumb->DebugMessage('PATH_INFO."w"x"h" set to "'.$_GET['w'].'"x"'.$_GET['h'].'"', __FILE__, __LINE__); + } + for ($i = 0; $i < count($args) - 2; $i++) { + @list($key, $value) = explode('=', @$args[$i]); + if (substr($key, -2) == '[]') { + $array_key_name = substr($key, 0, -2); + $_GET[$array_key_name][] = $value; + $phpThumb->DebugMessage('PATH_INFO."'.$array_key_name.'[]" = "'.$value.'"', __FILE__, __LINE__); + } else { + $_GET[$key] = $value; + $phpThumb->DebugMessage('PATH_INFO."'.$key.'" = "'.$value.'"', __FILE__, __LINE__); + } + } +} + +if (@$PHPTHUMB_CONFIG['high_security_enabled']) { + if (!@$_GET['hash']) { + $phpThumb->ErrorImage('ERROR: missing hash'); + } elseif (strlen($PHPTHUMB_CONFIG['high_security_password']) < 5) { + $phpThumb->ErrorImage('ERROR: strlen($PHPTHUMB_CONFIG[high_security_password]) < 5'); + } elseif ($_GET['hash'] != md5(str_replace('&hash='.$_GET['hash'], '', $_SERVER['QUERY_STRING']).$PHPTHUMB_CONFIG['high_security_password'])) { + $phpThumb->ErrorImage('ERROR: invalid hash'); + } +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[0]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '0') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +// returned the fixed string if the evil "magic_quotes_gpc" setting is on +if (get_magic_quotes_gpc()) { + $RequestVarsToStripSlashes = array('src', 'wmf', 'file', 'err', 'goto', 'down'); + foreach ($RequestVarsToStripSlashes as $key) { + if (isset($_GET[$key])) { + $_GET[$key] = stripslashes($_GET[$key]); + } + } +} + +if (!@$_SERVER['PATH_INFO'] && !@$_SERVER['QUERY_STRING']) { + $phpThumb->ErrorImage('phpThumb() v'.$phpThumb->phpthumb_version.'
    http://phpthumb.sourceforge.net

    ERROR: no parameters specified'); +} + +if (@$_GET['src'] && isset($_GET['md5s']) && empty($_GET['md5s'])) { + if (eregi('^(f|ht)tps?://', $_GET['src'])) { + if ($rawImageData = phpthumb_functions::SafeURLread($_GET['src'], $error, $phpThumb->config_http_fopen_timeout, $phpThumb->config_http_follow_redirect)) { + $md5s = md5($rawImageData); + } + } else { + $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($_GET['src']); + if (is_readable($SourceFilename)) { + $md5s = phpthumb_functions::md5_file_safe($SourceFilename); + } else { + $phpThumb->ErrorImage('ERROR: "'.$SourceFilename.'" cannot be read'); + } + } + if (@$_SERVER['HTTP_REFERER']) { + $phpThumb->ErrorImage('&md5s='.$md5s); + } else { + die('&md5s='.$md5s); + } +} + +if (!empty($PHPTHUMB_CONFIG)) { + foreach ($PHPTHUMB_CONFIG as $key => $value) { + $keyname = 'config_'.$key; + $phpThumb->setParameter($keyname, $value); + if (!eregi('password', $key)) { + $phpThumb->DebugMessage('setParameter('.$keyname.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + } + } +} else { + $phpThumb->DebugMessage('$PHPTHUMB_CONFIG is empty', __FILE__, __LINE__); +} + +if (@$_GET['src'] && !@$PHPTHUMB_CONFIG['allow_local_http_src'] && eregi('^http://'.@$_SERVER['HTTP_HOST'].'(.+)', @$_GET['src'], $matches)) { + $phpThumb->ErrorImage('It is MUCH better to specify the "src" parameter as "'.$matches[1].'" instead of "'.$matches[0].'".'."\n\n".'If you really must do it this way, enable "allow_local_http_src" in phpThumb.config.php'); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[1]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '1') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +$parsed_url_referer = parse_url(@$_SERVER['HTTP_REFERER']); +if ($phpThumb->config_nooffsitelink_require_refer && !in_array(@$parsed_url_referer['host'], $phpThumb->config_nohotlink_valid_domains)) { + $phpThumb->ErrorImage('config_nooffsitelink_require_refer enabled and '.(@$parsed_url_referer['host'] ? '"'.$parsed_url_referer['host'].'" is not an allowed referer' : 'no HTTP_REFERER exists')); +} +$parsed_url_src = parse_url(@$_GET['src']); +if ($phpThumb->config_nohotlink_enabled && $phpThumb->config_nohotlink_erase_image && eregi('^(f|ht)tps?://', @$_GET['src']) && !in_array(@$parsed_url_src['host'], $phpThumb->config_nohotlink_valid_domains)) { + $phpThumb->ErrorImage($phpThumb->config_nohotlink_text_message); +} + +if ($phpThumb->config_mysql_query) { + if ($cid = @mysql_connect($phpThumb->config_mysql_hostname, $phpThumb->config_mysql_username, $phpThumb->config_mysql_password)) { + if (@mysql_select_db($phpThumb->config_mysql_database, $cid)) { + if ($result = @mysql_query($phpThumb->config_mysql_query, $cid)) { + if ($row = @mysql_fetch_array($result)) { + + mysql_free_result($result); + mysql_close($cid); + $phpThumb->setSourceData($row[0]); + unset($row); + + } else { + mysql_free_result($result); + mysql_close($cid); + $phpThumb->ErrorImage('no matching data in database.'); + } + } else { + mysql_close($cid); + $phpThumb->ErrorImage('Error in MySQL query: "'.mysql_error($cid).'"'); + } + } else { + mysql_close($cid); + $phpThumb->ErrorImage('cannot select MySQL database: "'.mysql_error($cid).'"'); + } + } else { + $phpThumb->ErrorImage('cannot connect to MySQL server'); + } + unset($_GET['id']); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[2]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '2') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if (@$PHPTHUMB_CONFIG['cache_default_only_suffix'] && (strpos($PHPTHUMB_CONFIG['cache_default_only_suffix'], '*') !== false)) { + $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS = true; +} +// deprecated: 'err', 'file', 'goto', +$allowedGETparameters = array('src', 'new', 'w', 'h', 'wp', 'hp', 'wl', 'hl', 'ws', 'hs', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'zc', 'bc', 'bg', 'bgt', 'fltr', 'xto', 'ra', 'ar', 'aoe', 'far', 'iar', 'maxb', 'down', 'phpThumbDebug', 'hash', 'md5s', 'sfn', 'dpi', 'sia'); +if (!empty($PHPTHUMB_DEFAULTS) && is_array($PHPTHUMB_DEFAULTS)) { + $phpThumb->DebugMessage('setting $PHPTHUMB_DEFAULTS['.implode(';', array_keys($PHPTHUMB_DEFAULTS)).']', __FILE__, __LINE__); + foreach ($PHPTHUMB_DEFAULTS as $key => $value) { + if ($PHPTHUMB_DEFAULTS_GETSTRINGOVERRIDE || !isset($_GET[$key])) { + $_GET[$key] = $value; + $phpThumb->DebugMessage('PHPTHUMB_DEFAULTS assigning ('.$value.') to $_GET['.$key.']', __FILE__, __LINE__); + //$phpThumb->DebugMessage('PHPTHUMB_DEFAULTS.setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + //$phpThumb->setParameter($key, $value); + } + } +} +foreach ($_GET as $key => $value) { + if (@$PHPTHUMB_DEFAULTS_DISABLEGETPARAMS && ($key != 'src')) { + // disabled, do not set parameter + $phpThumb->DebugMessage('ignoring $_GET['.$key.'] because of $PHPTHUMB_DEFAULTS_DISABLEGETPARAMS', __FILE__, __LINE__); + } elseif (in_array($key, $allowedGETparameters)) { + $phpThumb->DebugMessage('setParameter('.$key.', '.$phpThumb->phpThumbDebugVarDump($value).')', __FILE__, __LINE__); + $phpThumb->setParameter($key, $value); + } else { + $phpThumb->ErrorImage('Forbidden parameter: '.$key); + } +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[3]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '3') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +//if (!@$_GET['phpThumbDebug'] && !$phpThumb->sourceFilename && !function_exists('ImageJPEG') && !function_exists('ImagePNG') && !function_exists('ImageGIF')) { +if (!@$_GET['phpThumbDebug'] && !is_file($phpThumb->sourceFilename) && !phpthumb_functions::gd_version()) { + if (!headers_sent()) { + // base64-encoded error image in GIF format + $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; + header('Content-Type: image/gif'); + echo base64_decode($ERROR_NOGD); + } else { + echo '*** ERROR: No PHP-GD support available ***'; + } + exit; +} + +// check to see if file can be output from source with no processing or caching +$CanPassThroughDirectly = true; +if ($phpThumb->rawImageData) { + // data from SQL, should be fine +} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because eregi("^(f|ht)tp\://", '.$phpThumb->src.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} elseif (!@is_file($phpThumb->sourceFilename)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_file('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} elseif (!@is_readable($phpThumb->sourceFilename)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because !@is_readable('.$phpThumb->sourceFilename.')', __FILE__, __LINE__); + $CanPassThroughDirectly = false; +} +foreach ($_GET as $key => $value) { + switch ($key) { + case 'src': + // allowed + break; + + case 'w': + case 'h': + // might be OK if exactly matches original + break; + + case 'phpThumbDebug': + // handled in direct-passthru code + break; + + default: + // all other parameters will cause some processing, + // therefore cannot pass through original image unmodified + $CanPassThroughDirectly = false; + $UnAllowedGET[] = $key; + break; + } +} +if (!empty($UnAllowedGET)) { + $phpThumb->DebugMessage('$CanPassThroughDirectly=false because $_GET['.implode(';', array_unique($UnAllowedGET)).'] are set', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[4]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '4') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +function SendSaveAsFileHeaderIfNeeded() { + if (headers_sent()) { + return false; + } + global $phpThumb; + $downloadfilename = phpthumb_functions::SanitizeFilename(@$_GET['sia'] ? $_GET['sia'] : (@$_GET['down'] ? $_GET['down'] : 'phpThumb_generated_thumbnail'.(@$_GET['f'] ? $_GET['f'] : 'jpg'))); + if (@$downloadfilename) { + $phpThumb->DebugMessage('SendSaveAsFileHeaderIfNeeded() sending header: Content-Disposition: '.(@$_GET['down'] ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"', __FILE__, __LINE__); + header('Content-Disposition: '.(@$_GET['down'] ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"'); + } + return true; +} + +$phpThumb->DebugMessage('$CanPassThroughDirectly="'.intval($CanPassThroughDirectly).'" && $phpThumb->src="'.$phpThumb->src.'"', __FILE__, __LINE__); +while ($CanPassThroughDirectly && $phpThumb->src) { + // no parameters set, passthru + $SourceFilename = $phpThumb->ResolveFilenameToAbsolute($phpThumb->src); + + // security and size checks + if ($phpThumb->getimagesizeinfo = @GetImageSize($SourceFilename)) { + $phpThumb->DebugMessage('Direct passthru GetImageSize() returned [w='.$phpThumb->getimagesizeinfo[0].';h='.$phpThumb->getimagesizeinfo[1].';t='.$phpThumb->getimagesizeinfo[2].']', __FILE__, __LINE__); + + if (!@$_GET['w'] && !@$_GET['wp'] && !@$_GET['wl'] && !@$_GET['ws'] && !@$_GET['h'] && !@$_GET['hp'] && !@$_GET['hl'] && !@$_GET['hs']) { + // no resizing needed + $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'")', __FILE__, __LINE__); + } elseif (($phpThumb->getimagesizeinfo[0] <= @$_GET['w']) && ($phpThumb->getimagesizeinfo[1] <= @$_GET['h']) && ((@$_GET['w'] == $phpThumb->getimagesizeinfo[0]) || (@$_GET['h'] == $phpThumb->getimagesizeinfo[1]))) { + // image fits into 'w'x'h' box, and at least one dimension matches exactly, therefore no resizing needed + $phpThumb->DebugMessage('Passing "'.$SourceFilename.'" through directly, no resizing required ("'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" fits inside "'.@$_GET['w'].'"x"'.@$_GET['h'].'")', __FILE__, __LINE__); + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because resizing required (from "'.$phpThumb->getimagesizeinfo[0].'"x"'.$phpThumb->getimagesizeinfo[1].'" to "'.@$_GET['w'].'"x"'.@$_GET['h'].'")', __FILE__, __LINE__); + break; + } + switch ($phpThumb->getimagesizeinfo[2]) { + case 1: // GIF + case 2: // JPG + case 3: // PNG + // great, let it through + break; + default: + // browser probably can't handle format, remangle it to JPEG/PNG/GIF + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because $phpThumb->getimagesizeinfo[2] = "'.$phpThumb->getimagesizeinfo[2].'"', __FILE__, __LINE__); + break 2; + } + + $ImageCreateFunctions = array(1=>'ImageCreateFromGIF', 2=>'ImageCreateFromJPEG', 3=>'ImageCreateFromPNG'); + $theImageCreateFunction = @$ImageCreateFunctions[$phpThumb->getimagesizeinfo[2]]; + if ($phpThumb->config_disable_onlycreateable_passthru || (function_exists($theImageCreateFunction) && ($dummyImage = @$theImageCreateFunction($SourceFilename)))) { + + // great + if (@is_resource($dummyImage)) { + unset($dummyImage); + } + + if (headers_sent()) { + $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); + exit; + } + if (@$_GET['phpThumbDebug']) { + $phpThumb->DebugTimingMessage('skipped direct $SourceFilename passthru', __FILE__, __LINE__); + $phpThumb->DebugMessage('Would have passed "'.$SourceFilename.'" through directly, but skipping due to phpThumbDebug', __FILE__, __LINE__); + break; + } + + SendSaveAsFileHeaderIfNeeded(); + header('Last-Modified: '.gmdate('D, d M Y H:i:s', @filemtime($SourceFilename)).' GMT'); + if ($contentType = phpthumb_functions::ImageTypeToMIMEtype(@$phpThumb->getimagesizeinfo[2])) { + header('Content-Type: '.$contentType); + } + @readfile($SourceFilename); + exit; + + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because ($phpThumb->config_disable_onlycreateable_passthru = "'.$phpThumb->config_disable_onlycreateable_passthru.'") and '.$theImageCreateFunction.'() failed', __FILE__, __LINE__); + break; + } + + } else { + $phpThumb->DebugMessage('Not passing "'.$SourceFilename.'" through directly because GetImageSize() failed', __FILE__, __LINE__); + break; + } + break; +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[5]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '5') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +function RedirectToCachedFile() { + global $phpThumb, $PHPTHUMB_CONFIG; + + $nice_cachefile = str_replace(DIRECTORY_SEPARATOR, '/', $phpThumb->cache_filename); + $nice_docroot = str_replace(DIRECTORY_SEPARATOR, '/', rtrim($PHPTHUMB_CONFIG['document_root'], '/\\')); + + $parsed_url = @parse_url(@$_SERVER['HTTP_REFERER']); + + $nModified = filemtime($phpThumb->cache_filename); + + if ($phpThumb->config_nooffsitelink_enabled && @$_SERVER['HTTP_REFERER'] && !in_array(@$parsed_url['host'], $phpThumb->config_nooffsitelink_valid_domains)) { + + $phpThumb->DebugMessage('Would have used cached (image/'.$phpThumb->thumbnailFormat.') file "'.$phpThumb->cache_filename.'" (Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT), but skipping because $_SERVER[HTTP_REFERER] ('.@$_SERVER['HTTP_REFERER'].') is not in $phpThumb->config_nooffsitelink_valid_domains ('.implode(';', $phpThumb->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + + } elseif ($phpThumb->phpThumbDebug) { + + $phpThumb->DebugTimingMessage('skipped using cached image', __FILE__, __LINE__); + $phpThumb->DebugMessage('Would have used cached file, but skipping due to phpThumbDebug', __FILE__, __LINE__); + $phpThumb->DebugMessage('* Would have sent headers (1): Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT', __FILE__, __LINE__); + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + $phpThumb->DebugMessage('* Would have sent headers (2): Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2]), __FILE__, __LINE__); + } + if (ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { + $phpThumb->DebugMessage('* Would have sent headers (3): Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1])), __FILE__, __LINE__); + } else { + $phpThumb->DebugMessage('* Would have sent data: readfile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); + } + + } else { + + if (headers_sent()) { + $phpThumb->ErrorImage('Headers already sent ('.basename(__FILE__).' line '.__LINE__.')'); + exit; + } + SendSaveAsFileHeaderIfNeeded(); + + header('Last-Modified: '.gmdate('D, d M Y H:i:s', $nModified).' GMT'); + if (@$_SERVER['HTTP_IF_MODIFIED_SINCE'] && ($nModified == strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) && @$_SERVER['SERVER_PROTOCOL']) { + header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); + exit; + } + + if ($getimagesize = @GetImageSize($phpThumb->cache_filename)) { + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($getimagesize[2])); + } elseif (eregi('\.ico$', $phpThumb->cache_filename)) { + header('Content-Type: image/x-icon'); + } + if (!@$PHPTHUMB_CONFIG['cache_force_passthru'] && ereg('^'.preg_quote($nice_docroot).'(.*)$', $nice_cachefile, $matches)) { + header('Location: '.dirname($matches[1]).'/'.urlencode(basename($matches[1]))); + } else { + @readfile($phpThumb->cache_filename); + } + exit; + + } + return true; +} + +// check to see if file already exists in cache, and output it with no processing if it does +$phpThumb->SetCacheFilename(); +if (@is_file($phpThumb->cache_filename)) { + RedirectToCachedFile(); +} else { + $phpThumb->DebugMessage('Cached file "'.$phpThumb->cache_filename.'" does not exist, processing as normal', __FILE__, __LINE__); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[6]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '6') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if ($phpThumb->rawImageData) { + + // great + +} elseif (@$_GET['new']) { + + // generate a blank image resource of the specified size/background color/opacity + if (($phpThumb->w <= 0) || ($phpThumb->h <= 0)) { + $phpThumb->ErrorImage('"w" and "h" parameters required for "new"'); + } + @list($bghexcolor, $opacity) = explode('|', $_GET['new']); + if (!phpthumb_functions::IsHexColor($bghexcolor)) { + $phpThumb->ErrorImage('BGcolor parameter for "new" is not valid'); + } + $opacity = (strlen($opacity) ? $opacity : 100); + if ($phpThumb->gdimg_source = phpthumb_functions::ImageCreateFunction($phpThumb->w, $phpThumb->h)) { + $alpha = (100 - min(100, max(0, $opacity))) * 1.27; + if ($alpha) { + $phpThumb->setParameter('is_alpha', true); + ImageAlphaBlending($phpThumb->gdimg_source, false); + ImageSaveAlpha($phpThumb->gdimg_source, true); + } + $new_background_color = phpthumb_functions::ImageHexColorAllocate($phpThumb->gdimg_source, $bghexcolor, false, $alpha); + ImageFilledRectangle($phpThumb->gdimg_source, 0, 0, $phpThumb->w, $phpThumb->h, $new_background_color); + } else { + $phpThumb->ErrorImage('failed to create "new" image ('.$phpThumb->w.'x'.$phpThumb->h.')'); + } + +} elseif (!$phpThumb->src) { + + $phpThumb->ErrorImage('Usage: '.$_SERVER['PHP_SELF'].'?src=/path/and/filename.jpg'."\n".'read Usage comments for details'); + +} elseif (eregi('^(f|ht)tp\://', $phpThumb->src)) { + + if ($phpThumb->config_http_user_agent) { + ini_set('user_agent', $phpThumb->config_http_user_agent); + } + + if ($rawImageData = phpthumb_functions::SafeURLread(phpthumb_functions::CleanUpURLencoding($phpThumb->src), $error, $phpThumb->config_http_fopen_timeout, $phpThumb->config_http_follow_redirect)) { + $phpThumb->setSourceData($rawImageData, urlencode($phpThumb->src)); + } else { + $phpThumb->ErrorImage($error); + } +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[7]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '7') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +$phpThumb->GenerateThumbnail(); + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[8]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '8') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if ($phpThumb->config_allow_parameter_file && $phpThumb->file) { + + $phpThumb->RenderToFile($phpThumb->ResolveFilenameToAbsolute($phpThumb->file)); + if ($phpThumb->config_allow_parameter_goto && $phpThumb->goto && eregi('^(f|ht)tps?://', $phpThumb->goto)) { + // redirect to another URL after image has been rendered to file + header('Location: '.$phpThumb->goto); + exit; + } + +} elseif (@$PHPTHUMB_CONFIG['high_security_enabled'] && @$_GET['nocache']) { + + // cache disabled, don't write cachefile + +} else { + + phpthumb_functions::EnsureDirectoryExists(dirname($phpThumb->cache_filename)); + if ((file_exists($phpThumb->cache_filename) && is_writable($phpThumb->cache_filename)) || is_writable(dirname($phpThumb->cache_filename))) { + + $phpThumb->CleanUpCacheDirectory(); + if ($phpThumb->RenderToFile($phpThumb->cache_filename) && is_readable($phpThumb->cache_filename)) { + chmod($phpThumb->cache_filename, 0644); + RedirectToCachedFile(); + } else { + $phpThumb->DebugMessage('Failed: RenderToFile('.$phpThumb->cache_filename.')', __FILE__, __LINE__); + } + + } else { + + $phpThumb->DebugMessage('Cannot write to $phpThumb->cache_filename ('.$phpThumb->cache_filename.') because that directory ('.dirname($phpThumb->cache_filename).') is not writable', __FILE__, __LINE__); + + } + +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[9]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '9') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +if (!$phpThumb->OutputThumbnail()) { + $phpThumb->ErrorImage('Error in OutputThumbnail():'."\n".$phpThumb->debugmessages[(count($phpThumb->debugmessages) - 1)]); +} + +//////////////////////////////////////////////////////////////// +// Debug output, to try and help me diagnose problems +$phpThumb->DebugTimingMessage('phpThumbDebug[10]', __FILE__, __LINE__); +if (@$_GET['phpThumbDebug'] == '10') { + $phpThumb->phpThumbDebug(); +} +//////////////////////////////////////////////////////////////// + +?> \ No newline at end of file diff --git a/common/phpThumb/phpthumb.bmp.php b/common/phpThumb/phpthumb.bmp.php new file mode 100644 index 0000000..d46ed13 --- /dev/null +++ b/common/phpThumb/phpthumb.bmp.php @@ -0,0 +1,874 @@ + // +// available at http://getid3.sourceforge.net // +// or http://www.getid3.org // +///////////////////////////////////////////////////////////////// +// See readme.txt for more details // +///////////////////////////////////////////////////////////////// +// // +// module.graphic.bmp.php // +// module for analyzing BMP Image files // +// dependencies: NONE // +// /// +///////////////////////////////////////////////////////////////// +// // +// Modified for use in phpThumb() - James Heinrich 2004.07.27 // +// // +///////////////////////////////////////////////////////////////// + + +class phpthumb_bmp { + + function phpthumb_bmp() { + return true; + } + + function phpthumb_bmp2gd(&$BMPdata, $truecolor=true) { + $ThisFileInfo = array(); + if ($this->getid3_bmp($BMPdata, $ThisFileInfo, true, true)) { + $gd = $this->PlotPixelsGD($ThisFileInfo['bmp'], $truecolor); + return $gd; + } + return false; + } + + function phpthumb_bmpfile2gd($filename, $truecolor=true) { + if ($fp = @fopen($filename, 'rb')) { + $BMPdata = fread($fp, filesize($filename)); + fclose($fp); + return $this->phpthumb_bmp2gd($BMPdata, $truecolor); + } + return false; + } + + function GD2BMPstring(&$gd_image) { + $imageX = ImageSX($gd_image); + $imageY = ImageSY($gd_image); + + $BMP = ''; + for ($y = ($imageY - 1); $y >= 0; $y--) { + $thisline = ''; + for ($x = 0; $x < $imageX; $x++) { + $argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y); + $thisline .= chr($argb['blue']).chr($argb['green']).chr($argb['red']); + } + while (strlen($thisline) % 4) { + $thisline .= "\x00"; + } + $BMP .= $thisline; + } + + $bmpSize = strlen($BMP) + 14 + 40; + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + $BITMAPFILEHEADER = 'BM'; // WORD bfType; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String($bmpSize, 4); // DWORD bfSize; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved1; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 0, 2); // WORD bfReserved2; + $BITMAPFILEHEADER .= phpthumb_functions::LittleEndian2String( 54, 4); // DWORD bfOffBits; + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + $BITMAPINFOHEADER = phpthumb_functions::LittleEndian2String( 40, 4); // DWORD biSize; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageX, 4); // LONG biWidth; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( $imageY, 4); // LONG biHeight; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 1, 2); // WORD biPlanes; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 24, 2); // WORD biBitCount; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biCompression; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biSizeImage; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biXPelsPerMeter; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 2835, 4); // LONG biYPelsPerMeter; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrUsed; + $BITMAPINFOHEADER .= phpthumb_functions::LittleEndian2String( 0, 4); // DWORD biClrImportant; + + return $BITMAPFILEHEADER.$BITMAPINFOHEADER.$BMP; + } + + function getid3_bmp(&$BMPdata, &$ThisFileInfo, $ExtractPalette=false, $ExtractData=false) { + + // shortcuts + $ThisFileInfo['bmp']['header']['raw'] = array(); + $thisfile_bmp = &$ThisFileInfo['bmp']; + $thisfile_bmp_header = &$thisfile_bmp['header']; + $thisfile_bmp_header_raw = &$thisfile_bmp_header['raw']; + + // BITMAPFILEHEADER [14 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_62uq.asp + // all versions + // WORD bfType; + // DWORD bfSize; + // WORD bfReserved1; + // WORD bfReserved2; + // DWORD bfOffBits; + + $offset = 0; + $overalloffset = 0; + $BMPheader = substr($BMPdata, $overalloffset, 14 + 40); + $overalloffset += (14 + 40); + + $thisfile_bmp_header_raw['identifier'] = substr($BMPheader, $offset, 2); + $offset += 2; + + if ($thisfile_bmp_header_raw['identifier'] != 'BM') { + $ThisFileInfo['error'][] = 'Expecting "BM" at offset '.intval(@$ThisFileInfo['avdataoffset']).', found "'.$thisfile_bmp_header_raw['identifier'].'"'; + unset($ThisFileInfo['fileformat']); + unset($ThisFileInfo['bmp']); + return false; + } + + $thisfile_bmp_header_raw['filesize'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['reserved2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['header_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + + // check if the hardcoded-to-1 "planes" is at offset 22 or 26 + $planes22 = $this->LittleEndian2Int(substr($BMPheader, 22, 2)); + $planes26 = $this->LittleEndian2Int(substr($BMPheader, 26, 2)); + if (($planes22 == 1) && ($planes26 != 1)) { + $thisfile_bmp['type_os'] = 'OS/2'; + $thisfile_bmp['type_version'] = 1; + } elseif (($planes26 == 1) && ($planes22 != 1)) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 12) { + $thisfile_bmp['type_os'] = 'OS/2'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 40) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 1; + } elseif ($thisfile_bmp_header_raw['header_size'] == 84) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 4; + } elseif ($thisfile_bmp_header_raw['header_size'] == 100) { + $thisfile_bmp['type_os'] = 'Windows'; + $thisfile_bmp['type_version'] = 5; + } else { + $ThisFileInfo['error'][] = 'Unknown BMP subtype (or not a BMP file)'; + unset($ThisFileInfo['fileformat']); + unset($ThisFileInfo['bmp']); + return false; + } + + $ThisFileInfo['fileformat'] = 'bmp'; + $ThisFileInfo['video']['dataformat'] = 'bmp'; + $ThisFileInfo['video']['lossless'] = true; + $ThisFileInfo['video']['pixel_aspect_ratio'] = (float) 1; + + if ($thisfile_bmp['type_os'] == 'OS/2') { + + // OS/2-format BMP + // http://netghost.narod.ru/gff/graphics/summary/os2bmp.htm + + // DWORD Size; /* Size of this structure in bytes */ + // DWORD Width; /* Bitmap width in pixels */ + // DWORD Height; /* Bitmap height in pixel */ + // WORD NumPlanes; /* Number of bit planes (color depth) */ + // WORD BitsPerPixel; /* Number of bits per pixel per plane */ + + $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + + $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; + $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; + $ThisFileInfo['video']['codec'] = 'BI_RGB '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; + + if ($thisfile_bmp['type_version'] >= 2) { + // DWORD Compression; /* Bitmap compression scheme */ + // DWORD ImageDataSize; /* Size of bitmap data in bytes */ + // DWORD XResolution; /* X resolution of display device */ + // DWORD YResolution; /* Y resolution of display device */ + // DWORD ColorsUsed; /* Number of color table indices used */ + // DWORD ColorsImportant; /* Number of important color indices */ + // WORD Units; /* Type of units used to measure resolution */ + // WORD Reserved; /* Pad structure to 4-byte boundary */ + // WORD Recording; /* Recording algorithm */ + // WORD Rendering; /* Halftoning algorithm used */ + // DWORD Size1; /* Reserved for halftoning algorithm use */ + // DWORD Size2; /* Reserved for halftoning algorithm use */ + // DWORD ColorEncoding; /* Color model used in bitmap */ + // DWORD Identifier; /* Reserved for application use */ + + $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_units'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['reserved1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['recording'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['rendering'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['size1'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['size2'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['color_encoding'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['identifier'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['compression'] = $this->BMPcompressionOS2Lookup($thisfile_bmp_header_raw['compression']); + + $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + } + + } elseif ($thisfile_bmp['type_os'] == 'Windows') { + + // Windows-format BMP + + // BITMAPINFOHEADER - [40 bytes] http://msdn.microsoft.com/library/en-us/gdi/bitmaps_1rw2.asp + // all versions + // DWORD biSize; + // LONG biWidth; + // LONG biHeight; + // WORD biPlanes; + // WORD biBitCount; + // DWORD biCompression; + // DWORD biSizeImage; + // LONG biXPelsPerMeter; + // LONG biYPelsPerMeter; + // DWORD biClrUsed; + // DWORD biClrImportant; + + $thisfile_bmp_header_raw['width'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['height'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['planes'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['bits_per_pixel'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 2)); + $offset += 2; + $thisfile_bmp_header_raw['compression'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['bmp_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['resolution_h'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['resolution_v'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4), true); + $offset += 4; + $thisfile_bmp_header_raw['colors_used'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['colors_important'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['compression'] = $this->BMPcompressionWindowsLookup($thisfile_bmp_header_raw['compression']); + $ThisFileInfo['video']['resolution_x'] = $thisfile_bmp_header_raw['width']; + $ThisFileInfo['video']['resolution_y'] = $thisfile_bmp_header_raw['height']; + $ThisFileInfo['video']['codec'] = $thisfile_bmp_header['compression'].' '.$thisfile_bmp_header_raw['bits_per_pixel'].'-bit'; + $ThisFileInfo['video']['bits_per_sample'] = $thisfile_bmp_header_raw['bits_per_pixel']; + + if (($thisfile_bmp['type_version'] >= 4) || ($thisfile_bmp_header_raw['compression'] == 3)) { + // should only be v4+, but BMPs with type_version==1 and BI_BITFIELDS compression have been seen + $BMPheader .= substr($BMPdata, $overalloffset, 44); + $overalloffset += 44; + + // BITMAPV4HEADER - [44 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_2k1e.asp + // Win95+, WinNT4.0+ + // DWORD bV4RedMask; + // DWORD bV4GreenMask; + // DWORD bV4BlueMask; + // DWORD bV4AlphaMask; + // DWORD bV4CSType; + // CIEXYZTRIPLE bV4Endpoints; + // DWORD bV4GammaRed; + // DWORD bV4GammaGreen; + // DWORD bV4GammaBlue; + $thisfile_bmp_header_raw['red_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['green_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['blue_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['alpha_mask'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['cs_type'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_red'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_green'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['ciexyz_blue'] = substr($BMPheader, $offset, 4); + $offset += 4; + $thisfile_bmp_header_raw['gamma_red'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['gamma_green'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['gamma_blue'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + + $thisfile_bmp_header['ciexyz_red'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_red'])); + $thisfile_bmp_header['ciexyz_green'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_green'])); + $thisfile_bmp_header['ciexyz_blue'] = $this->FixedPoint2_30(strrev($thisfile_bmp_header_raw['ciexyz_blue'])); + } + + if ($thisfile_bmp['type_version'] >= 5) { + $BMPheader .= substr($BMPdata, $overalloffset, 16); + $overalloffset += 16; + + // BITMAPV5HEADER - [16 bytes] - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_7c36.asp + // Win98+, Win2000+ + // DWORD bV5Intent; + // DWORD bV5ProfileData; + // DWORD bV5ProfileSize; + // DWORD bV5Reserved; + $thisfile_bmp_header_raw['intent'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['profile_data_offset'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['profile_data_size'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + $thisfile_bmp_header_raw['reserved3'] = $this->LittleEndian2Int(substr($BMPheader, $offset, 4)); + $offset += 4; + } + + } else { + + $ThisFileInfo['error'][] = 'Unknown BMP format in header.'; + return false; + + } + + if ($ExtractPalette || $ExtractData) { + $PaletteEntries = 0; + if ($thisfile_bmp_header_raw['bits_per_pixel'] < 16) { + $PaletteEntries = pow(2, $thisfile_bmp_header_raw['bits_per_pixel']); + } elseif (isset($thisfile_bmp_header_raw['colors_used']) && ($thisfile_bmp_header_raw['colors_used'] > 0) && ($thisfile_bmp_header_raw['colors_used'] <= 256)) { + $PaletteEntries = $thisfile_bmp_header_raw['colors_used']; + } + if ($PaletteEntries > 0) { + $BMPpalette = substr($BMPdata, $overalloffset, 4 * $PaletteEntries); + $overalloffset += 4 * $PaletteEntries; + + $paletteoffset = 0; + for ($i = 0; $i < $PaletteEntries; $i++) { + // RGBQUAD - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_5f8y.asp + // BYTE rgbBlue; + // BYTE rgbGreen; + // BYTE rgbRed; + // BYTE rgbReserved; + $blue = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + $green = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + $red = $this->LittleEndian2Int(substr($BMPpalette, $paletteoffset++, 1)); + if (($thisfile_bmp['type_os'] == 'OS/2') && ($thisfile_bmp['type_version'] == 1)) { + // no padding byte + } else { + $paletteoffset++; // padding byte + } + $thisfile_bmp['palette'][$i] = (($red << 16) | ($green << 8) | ($blue)); + } + } + } + + if ($ExtractData) { + $RowByteLength = ceil(($thisfile_bmp_header_raw['width'] * ($thisfile_bmp_header_raw['bits_per_pixel'] / 8)) / 4) * 4; // round up to nearest DWORD boundry + + $BMPpixelData = substr($BMPdata, $thisfile_bmp_header_raw['data_offset'], $thisfile_bmp_header_raw['height'] * $RowByteLength); + $overalloffset = $thisfile_bmp_header_raw['data_offset'] + ($thisfile_bmp_header_raw['height'] * $RowByteLength); + + $pixeldataoffset = 0; + switch (@$thisfile_bmp_header_raw['compression']) { + + case 0: // BI_RGB + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 1: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { + $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); + for ($i = 7; $i >= 0; $i--) { + $paletteindex = ($paletteindexbyte & (0x01 << $i)) >> $i; + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $col++; + } + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 4: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col = $col) { + $paletteindexbyte = ord($BMPpixelData{$pixeldataoffset++}); + for ($i = 1; $i >= 0; $i--) { + $paletteindex = ($paletteindexbyte & (0x0F << (4 * $i))) >> (4 * $i); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $col++; + } + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 8: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $paletteindex = ord($BMPpixelData{$pixeldataoffset++}); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 24: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); + $pixeldataoffset += 3; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 32: + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $thisfile_bmp['data'][$row][$col] = (ord($BMPpixelData{$pixeldataoffset+3}) << 24) | (ord($BMPpixelData{$pixeldataoffset+2}) << 16) | (ord($BMPpixelData{$pixeldataoffset+1}) << 8) | ord($BMPpixelData{$pixeldataoffset}); + $pixeldataoffset += 4; + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + case 16: + // ? + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + case 1: // BI_RLE8 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 8: + $pixelcounter = 0; + while ($pixeldataoffset < strlen($BMPpixelData)) { + $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + if ($firstbyte == 0) { + + // escaped/absolute mode - the first byte of the pair can be set to zero to + // indicate an escape character that denotes the end of a line, the end of + // a bitmap, or a delta, depending on the value of the second byte. + switch ($secondbyte) { + case 0: + // end of line + // no need for special processing, just ignore + break; + + case 1: + // end of bitmap + $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case + break; + + case 2: + // delta - The 2 bytes following the escape contain unsigned values + // indicating the horizontal and vertical offsets of the next pixel + // from the current position. + $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; + $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; + $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; + break; + + default: + // In absolute mode, the first byte is zero and the second byte is a + // value in the range 03H through FFH. The second byte represents the + // number of bytes that follow, each of which contains the color index + // of a single pixel. Each run must be aligned on a word boundary. + for ($i = 0; $i < $secondbyte; $i++) { + $paletteindex = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $pixelcounter++; + } + while (($pixeldataoffset % 2) != 0) { + // Each run must be aligned on a word boundary. + $pixeldataoffset++; + } + break; + } + + } else { + + // encoded mode - the first byte specifies the number of consecutive pixels + // to be drawn using the color index contained in the second byte. + for ($i = 0; $i < $firstbyte; $i++) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$secondbyte]; + $pixelcounter++; + } + + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + + case 2: // BI_RLE4 - http://msdn.microsoft.com/library/en-us/gdi/bitmaps_6x0u.asp + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 4: + $pixelcounter = 0; + while ($pixeldataoffset < strlen($BMPpixelData)) { + $firstbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $secondbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + if ($firstbyte == 0) { + + // escaped/absolute mode - the first byte of the pair can be set to zero to + // indicate an escape character that denotes the end of a line, the end of + // a bitmap, or a delta, depending on the value of the second byte. + switch ($secondbyte) { + case 0: + // end of line + // no need for special processing, just ignore + break; + + case 1: + // end of bitmap + $pixeldataoffset = strlen($BMPpixelData); // force to exit loop just in case + break; + + case 2: + // delta - The 2 bytes following the escape contain unsigned values + // indicating the horizontal and vertical offsets of the next pixel + // from the current position. + $colincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $rowincrement = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $col = ($pixelcounter % $thisfile_bmp_header_raw['width']) + $colincrement; + $row = ($thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width'])) - $rowincrement; + $pixelcounter = ($row * $thisfile_bmp_header_raw['width']) + $col; + break; + + default: + // In absolute mode, the first byte is zero. The second byte contains the number + // of color indexes that follow. Subsequent bytes contain color indexes in their + // high- and low-order 4 bits, one color index for each pixel. In absolute mode, + // each run must be aligned on a word boundary. + unset($paletteindexes); + for ($i = 0; $i < ceil($secondbyte / 2); $i++) { + $paletteindexbyte = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset++, 1)); + $paletteindexes[] = ($paletteindexbyte & 0xF0) >> 4; + $paletteindexes[] = ($paletteindexbyte & 0x0F); + } + while (($pixeldataoffset % 2) != 0) { + // Each run must be aligned on a word boundary. + $pixeldataoffset++; + } + + foreach ($paletteindexes as $dummy => $paletteindex) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindex]; + $pixelcounter++; + } + break; + } + + } else { + + // encoded mode - the first byte of the pair contains the number of pixels to be + // drawn using the color indexes in the second byte. The second byte contains two + // color indexes, one in its high-order 4 bits and one in its low-order 4 bits. + // The first of the pixels is drawn using the color specified by the high-order + // 4 bits, the second is drawn using the color in the low-order 4 bits, the third + // is drawn using the color in the high-order 4 bits, and so on, until all the + // pixels specified by the first byte have been drawn. + $paletteindexes[0] = ($secondbyte & 0xF0) >> 4; + $paletteindexes[1] = ($secondbyte & 0x0F); + for ($i = 0; $i < $firstbyte; $i++) { + $col = $pixelcounter % $thisfile_bmp_header_raw['width']; + $row = $thisfile_bmp_header_raw['height'] - 1 - (($pixelcounter - $col) / $thisfile_bmp_header_raw['width']); + $thisfile_bmp['data'][$row][$col] = $thisfile_bmp['palette'][$paletteindexes[($i % 2)]]; + $pixelcounter++; + } + + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + case 3: // BI_BITFIELDS + switch ($thisfile_bmp_header_raw['bits_per_pixel']) { + case 16: + case 32: + $redshift = 0; + $greenshift = 0; + $blueshift = 0; + if (!$thisfile_bmp_header_raw['red_mask'] || !$thisfile_bmp_header_raw['green_mask'] || !$thisfile_bmp_header_raw['blue_mask']) { + $ThisFileInfo['error'][] = 'missing $thisfile_bmp_header_raw[(red|green|blue)_mask]'; + return false; + } + while ((($thisfile_bmp_header_raw['red_mask'] >> $redshift) & 0x01) == 0) { + $redshift++; + } + while ((($thisfile_bmp_header_raw['green_mask'] >> $greenshift) & 0x01) == 0) { + $greenshift++; + } + while ((($thisfile_bmp_header_raw['blue_mask'] >> $blueshift) & 0x01) == 0) { + $blueshift++; + } + for ($row = ($thisfile_bmp_header_raw['height'] - 1); $row >= 0; $row--) { + for ($col = 0; $col < $thisfile_bmp_header_raw['width']; $col++) { + $pixelvalue = $this->LittleEndian2Int(substr($BMPpixelData, $pixeldataoffset, $thisfile_bmp_header_raw['bits_per_pixel'] / 8)); + $pixeldataoffset += $thisfile_bmp_header_raw['bits_per_pixel'] / 8; + + $red = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['red_mask']) >> $redshift) / ($thisfile_bmp_header_raw['red_mask'] >> $redshift)) * 255)); + $green = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['green_mask']) >> $greenshift) / ($thisfile_bmp_header_raw['green_mask'] >> $greenshift)) * 255)); + $blue = intval(round(((($pixelvalue & $thisfile_bmp_header_raw['blue_mask']) >> $blueshift) / ($thisfile_bmp_header_raw['blue_mask'] >> $blueshift)) * 255)); + $thisfile_bmp['data'][$row][$col] = (($red << 16) | ($green << 8) | ($blue)); + } + while (($pixeldataoffset % 4) != 0) { + // lines are padded to nearest DWORD + $pixeldataoffset++; + } + } + break; + + default: + $ThisFileInfo['error'][] = 'Unknown bits-per-pixel value ('.$thisfile_bmp_header_raw['bits_per_pixel'].') - cannot read pixel data'; + break; + } + break; + + + default: // unhandled compression type + $ThisFileInfo['error'][] = 'Unknown/unhandled compression type value ('.$thisfile_bmp_header_raw['compression'].') - cannot decompress pixel data'; + break; + } + } + + return true; + } + + function IntColor2RGB($color) { + $red = ($color & 0x00FF0000) >> 16; + $green = ($color & 0x0000FF00) >> 8; + $blue = ($color & 0x000000FF); + return array($red, $green, $blue); + } + + function PlotPixelsGD(&$BMPdata, $truecolor=true) { + $imagewidth = $BMPdata['header']['raw']['width']; + $imageheight = $BMPdata['header']['raw']['height']; + + if ($truecolor) { + + $gd = @ImageCreateTrueColor($imagewidth, $imageheight); + + } else { + + $gd = @ImageCreate($imagewidth, $imageheight); + if (!empty($BMPdata['palette'])) { + // create GD palette from BMP palette + foreach ($BMPdata['palette'] as $dummy => $color) { + list($r, $g, $b) = $this->IntColor2RGB($color); + ImageColorAllocate($gd, $r, $g, $b); + } + } else { + // create 216-color websafe palette + for ($r = 0x00; $r <= 0xFF; $r += 0x33) { + for ($g = 0x00; $g <= 0xFF; $g += 0x33) { + for ($b = 0x00; $b <= 0xFF; $b += 0x33) { + ImageColorAllocate($gd, $r, $g, $b); + } + } + } + } + + } + if (!is_resource($gd)) { + return false; + } + + foreach ($BMPdata['data'] as $row => $colarray) { + @set_time_limit(30); + foreach ($colarray as $col => $color) { + list($red, $green, $blue) = $this->IntColor2RGB($color); + if ($truecolor) { + $pixelcolor = ImageColorAllocate($gd, $red, $green, $blue); + } else { + $pixelcolor = ImageColorClosest($gd, $red, $green, $blue); + } + ImageSetPixel($gd, $col, $row, $pixelcolor); + } + } + return $gd; + } + + function PlotBMP(&$BMPinfo) { + $starttime = time(); + if (!isset($BMPinfo['bmp']['data']) || !is_array($BMPinfo['bmp']['data'])) { + echo 'ERROR: no pixel data
    '; + return false; + } + set_time_limit(intval(round($BMPinfo['resolution_x'] * $BMPinfo['resolution_y'] / 10000))); + $im = $this->PlotPixelsGD($BMPinfo['bmp']); + if (headers_sent()) { + echo 'plotted '.($BMPinfo['resolution_x'] * $BMPinfo['resolution_y']).' pixels in '.(time() - $starttime).' seconds
    '; + ImageDestroy($im); + exit; + } else { + header('Content-Type: image/png'); + ImagePNG($im); + ImageDestroy($im); + return true; + } + return false; + } + + function BMPcompressionWindowsLookup($compressionid) { + static $BMPcompressionWindowsLookup = array( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'BI_BITFIELDS', + 4 => 'BI_JPEG', + 5 => 'BI_PNG' + ); + return (isset($BMPcompressionWindowsLookup[$compressionid]) ? $BMPcompressionWindowsLookup[$compressionid] : 'invalid'); + } + + function BMPcompressionOS2Lookup($compressionid) { + static $BMPcompressionOS2Lookup = array( + 0 => 'BI_RGB', + 1 => 'BI_RLE8', + 2 => 'BI_RLE4', + 3 => 'Huffman 1D', + 4 => 'BI_RLE24', + ); + return (isset($BMPcompressionOS2Lookup[$compressionid]) ? $BMPcompressionOS2Lookup[$compressionid] : 'invalid'); + } + + + // from getid3.lib.php + + function trunc($floatnumber) { + // truncates a floating-point number at the decimal point + // returns int (if possible, otherwise float) + if ($floatnumber >= 1) { + $truncatednumber = floor($floatnumber); + } elseif ($floatnumber <= -1) { + $truncatednumber = ceil($floatnumber); + } else { + $truncatednumber = 0; + } + if ($truncatednumber <= 1073741824) { // 2^30 + $truncatednumber = (int) $truncatednumber; + } + return $truncatednumber; + } + + function LittleEndian2Int($byteword) { + $intvalue = 0; + $byteword = strrev($byteword); + $bytewordlen = strlen($byteword); + for ($i = 0; $i < $bytewordlen; $i++) { + $intvalue += ord($byteword{$i}) * pow(256, ($bytewordlen - 1 - $i)); + } + return $intvalue; + } + + function BigEndian2Int($byteword) { + return $this->LittleEndian2Int(strrev($byteword)); + } + + function BigEndian2Bin($byteword) { + $binvalue = ''; + $bytewordlen = strlen($byteword); + for ($i = 0; $i < $bytewordlen; $i++) { + $binvalue .= str_pad(decbin(ord($byteword{$i})), 8, '0', STR_PAD_LEFT); + } + return $binvalue; + } + + function FixedPoint2_30($rawdata) { + $binarystring = $this->BigEndian2Bin($rawdata); + return $this->Bin2Dec(substr($binarystring, 0, 2)) + (float) ($this->Bin2Dec(substr($binarystring, 2, 30)) / 1073741824); + } + + function Bin2Dec($binstring, $signed=false) { + $signmult = 1; + if ($signed) { + if ($binstring{0} == '1') { + $signmult = -1; + } + $binstring = substr($binstring, 1); + } + $decvalue = 0; + for ($i = 0; $i < strlen($binstring); $i++) { + $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i); + } + return $this->CastAsInt($decvalue * $signmult); + } + + function CastAsInt($floatnum) { + // convert to float if not already + $floatnum = (float) $floatnum; + + // convert a float to type int, only if possible + if ($this->trunc($floatnum) == $floatnum) { + // it's not floating point + if ($floatnum <= 1073741824) { // 2^30 + // it's within int range + $floatnum = (int) $floatnum; + } + } + return $floatnum; + } + +} + +?> \ No newline at end of file diff --git a/common/phpThumb/phpthumb.class.php b/common/phpThumb/phpthumb.class.php new file mode 100644 index 0000000..8460604 --- /dev/null +++ b/common/phpThumb/phpthumb.class.php @@ -0,0 +1,3624 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// See: phpthumb.readme.txt for usage instructions // +// /// +////////////////////////////////////////////////////////////// + +ob_start(); +if (!include_once(dirname(__FILE__).'/phpthumb.functions.php')) { + ob_end_flush(); + die('failed to include_once("'.realpath(dirname(__FILE__).'/phpthumb.functions.php').'")'); +} +ob_end_clean(); + +class phpthumb { + + // public: + // START PARAMETERS (for object mode and phpThumb.php) + // See phpthumb.readme.txt for descriptions of what each of these values are + var $src = null; // SouRCe filename + var $new = null; // NEW image (phpThumb.php only) + var $w = null; // Width + var $h = null; // Height + var $wp = null; // Width (Portrait Images Only) + var $hp = null; // Height (Portrait Images Only) + var $wl = null; // Width (Landscape Images Only) + var $hl = null; // Height (Landscape Images Only) + var $ws = null; // Width (Square Images Only) + var $hs = null; // Height (Square Images Only) + var $f = null; // Format + var $q = 100; // jpeg output Quality + var $sx = null; // Source crop top-left X position + var $sy = null; // Source crop top-left Y position + var $sw = null; // Source crop Width + var $sh = null; // Source crop Height + var $zc = null; // Zoom Crop + var $bc = null; // Border Color + var $bg = null; // BackGround color + var $fltr = array(); // FiLTeRs + var $goto = null; // GO TO url after processing + var $err = null; // default ERRor image filename + var $xto = null; // extract eXif Thumbnail Only + var $ra = null; // Rotate by Angle + var $ar = null; // Auto Rotate + var $aoe = null; // Allow Output Enlargement + var $far = null; // Fixed Aspect Ratio + var $iar = null; // Ignore Aspect Ratio + var $maxb = null; // MAXimum Bytes + var $down = null; // DOWNload thumbnail filename + var $md5s = null; // MD5 hash of Source image + var $sfn = 0; // Source Frame Number + var $dpi = 150; // Dots Per Inch for vector source formats + var $sia = null; // Save Image As filename + + var $file = null; // >>>deprecated, DO NOT USE, will be removed in future versions<<< + + var $phpThumbDebug = null; + // END PARAMETERS + + + // public: + // START CONFIGURATION OPTIONS (for object mode only) + // See phpThumb.config.php for descriptions of what each of these settings do + + // * Directory Configuration + var $config_cache_directory = null; + var $config_cache_directory_depth = 0; + var $config_cache_disable_warning = true; + var $config_cache_source_enabled = false; + var $config_cache_source_directory = null; + var $config_temp_directory = null; + var $config_document_root = null; + + // * Default output configuration: + var $config_output_format = 'jpeg'; + var $config_output_maxwidth = 0; + var $config_output_maxheight = 0; + var $config_output_interlace = true; + + // * Error message configuration + var $config_error_image_width = 400; + var $config_error_image_height = 100; + var $config_error_message_image_default = ''; + var $config_error_bgcolor = 'CCCCFF'; + var $config_error_textcolor = 'FF0000'; + var $config_error_fontsize = 1; + var $config_error_die_on_error = false; + var $config_error_silent_die_on_error = false; + var $config_error_die_on_source_failure = true; + + // * Anti-Hotlink Configuration: + var $config_nohotlink_enabled = true; + var $config_nohotlink_valid_domains = array(); + var $config_nohotlink_erase_image = true; + var $config_nohotlink_text_message = 'Off-server thumbnailing is not allowed'; + // * Off-server Linking Configuration: + var $config_nooffsitelink_enabled = false; + var $config_nooffsitelink_valid_domains = array(); + var $config_nooffsitelink_require_refer = false; + var $config_nooffsitelink_erase_image = true; + var $config_nooffsitelink_watermark_src = ''; + var $config_nooffsitelink_text_message = 'Off-server linking is not allowed'; + + // * Border & Background default colors + var $config_border_hexcolor = '000000'; + var $config_background_hexcolor = 'FFFFFF'; + + // * TrueType Fonts + var $config_ttf_directory = '.'; + + var $config_max_source_pixels = null; + var $config_use_exif_thumbnail_for_speed = false; + var $allow_local_http_src = false; + + var $config_imagemagick_path = null; + var $config_prefer_imagemagick = true; + var $config_imagemagick_use_thumbnail = true; + + var $config_cache_maxage = null; + var $config_cache_maxsize = null; + var $config_cache_maxfiles = null; + var $config_cache_source_filemtime_ignore_local = false; + var $config_cache_source_filemtime_ignore_remote = true; + var $config_cache_default_only_suffix = false; + var $config_cache_force_passthru = true; + var $config_cache_prefix = ''; // default value set in the constructor below + + // * MySQL + var $config_mysql_query = null; + var $config_mysql_hostname = null; + var $config_mysql_username = null; + var $config_mysql_password = null; + var $config_mysql_database = null; + + // * Security + var $config_high_security_enabled = false; + var $config_high_security_password = null; + var $config_disable_debug = false; + var $config_allow_src_above_docroot = false; + var $config_allow_src_above_phpthumb = true; + var $config_allow_parameter_file = false; + var $config_allow_parameter_goto = false; + + // * HTTP fopen + var $config_http_fopen_timeout = 10; + var $config_http_follow_redirect = true; + + // * Compatability + var $config_disable_pathinfo_parsing = false; + var $config_disable_imagecopyresampled = false; + var $config_disable_onlycreateable_passthru = false; + + var $config_http_user_agent = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.12) Gecko/20050915 Firefox/1.0.7'; + + // END CONFIGURATION OPTIONS + + + // public: error messages (read-only) + var $debugmessages = array(); + var $debugtiming = array(); + var $fatalerror = null; + + + // private: (should not be modified directly) + var $thumbnailQuality = 75; + var $thumbnailFormat = null; + + var $sourceFilename = null; + var $rawImageData = null; + var $IMresizedData = null; + var $outputImageData = null; + + var $useRawIMoutput = false; + + var $gdimg_output = null; + var $gdimg_source = null; + + var $getimagesizeinfo = null; + + var $source_width = null; + var $source_height = null; + + var $thumbnailCropX = null; + var $thumbnailCropY = null; + var $thumbnailCropW = null; + var $thumbnailCropH = null; + + var $exif_thumbnail_width = null; + var $exif_thumbnail_height = null; + var $exif_thumbnail_type = null; + var $exif_thumbnail_data = null; + var $exif_raw_data = null; + + var $thumbnail_width = null; + var $thumbnail_height = null; + var $thumbnail_image_width = null; + var $thumbnail_image_height = null; + + var $cache_filename = null; + + var $AlphaCapableFormats = array('png', 'ico', 'gif'); + var $is_alpha = false; + + var $iswindows = null; + + var $phpthumb_version = '1.7.7-200612252156'; + + ////////////////////////////////////////////////////////////////////// + + // public: constructor + function phpThumb() { + $this->DebugTimingMessage('phpThumb() constructor', __FILE__, __LINE__); + $this->DebugMessage('phpThumb() v'.$this->phpthumb_version, __FILE__, __LINE__); + $this->config_max_source_pixels = round(max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576 * 0.20); // 20% of memory_limit + $this->iswindows = (bool) (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'); + $this->config_temp_directory = realpath($this->config_temp_directory ? $this->config_temp_directory : (getenv('TMPDIR') ? getenv('TMPDIR') : getenv('TMP'))); + $this->config_document_root = (@$_SERVER['DOCUMENT_ROOT'] ? $_SERVER['DOCUMENT_ROOT'] : $this->config_document_root); + $this->config_cache_prefix = 'phpThumb_cache_'.@$_SERVER['SERVER_NAME']; + + $php_sapi_name = strtolower(function_exists('php_sapi_name') ? php_sapi_name() : ''); + if ($php_sapi_name == 'cli') { + $this->config_allow_src_above_docroot = true; + } + } + + // public: + function setSourceFilename($sourceFilename) { + $this->rawImageData = null; + $this->sourceFilename = $sourceFilename; + $this->src = $sourceFilename; + $this->DebugMessage('setSourceFilename('.$sourceFilename.') set $this->sourceFilename to "'.$this->sourceFilename.'"', __FILE__, __LINE__); + return true; + } + + // public: + function setSourceData($rawImageData, $sourceFilename='') { + $this->sourceFilename = null; + $this->rawImageData = $rawImageData; + $this->DebugMessage('setSourceData() setting $this->rawImageData ('.strlen($this->rawImageData).' bytes)', __FILE__, __LINE__); + if ($this->config_cache_source_enabled) { + $sourceFilename = ($sourceFilename ? $sourceFilename : md5($rawImageData)); + if (!is_dir($this->config_cache_source_directory)) { + $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not a directory'); + } elseif (!@is_writable($this->config_cache_source_directory)) { + $this->ErrorImage('$this->config_cache_source_directory ('.$this->config_cache_source_directory.') is not writable'); + } + $this->DebugMessage('setSourceData() attempting to save source image to "'.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).'"', __FILE__, __LINE__); + if ($fp = @fopen($this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename), 'wb')) { + fwrite($fp, $rawImageData); + fclose($fp); + } elseif (!$this->phpThumbDebug) { + $this->ErrorImage('setSourceData() failed to write to source cache ('.$this->config_cache_source_directory.DIRECTORY_SEPARATOR.urlencode($sourceFilename).')'); + } + } + return true; + } + + // public: + function setSourceImageResource($gdimg) { + $this->gdimg_source = $gdimg; + return true; + } + + // public: + function setParameter($param, $value) { + if ($param == 'src') { + $this->setSourceFilename($this->ResolveFilenameToAbsolute($value)); + } elseif (@is_array($this->$param)) { + if (is_array($value)) { + foreach ($value as $arraykey => $arrayvalue) { + array_push($this->$param, $arrayvalue); + } + } else { + array_push($this->$param, $value); + } + } else { + $this->$param = $value; + } + return true; + } + + // public: + function getParameter($param) { + //if (property_exists('phpThumb', $param)) { + return $this->$param; + //} + //$this->DebugMessage('setParameter() attempting to get non-existant parameter "'.$param.'"', __FILE__, __LINE__); + //return false; + } + + + // public: + function GenerateThumbnail() { + + $this->setOutputFormat(); + $this->phpThumbDebug('8a'); + $this->ResolveSource(); + $this->phpThumbDebug('8b'); + $this->SetCacheFilename(); + $this->phpThumbDebug('8c'); + $this->ExtractEXIFgetImageSize(); + $this->phpThumbDebug('8d'); + if ($this->useRawIMoutput) { + $this->DebugMessage('Skipping rest of GenerateThumbnail() because $this->useRawIMoutput', __FILE__, __LINE__); + return true; + } + $this->phpThumbDebug('8e'); + if (!$this->SourceImageToGD()) { + $this->DebugMessage('SourceImageToGD() failed', __FILE__, __LINE__); + return false; + } + $this->phpThumbDebug('8f'); + $this->Rotate(); + $this->phpThumbDebug('8g'); + $this->CreateGDoutput(); + $this->phpThumbDebug('8h'); + + switch ($this->far) { + case 'L': + case 'TL': + case 'BL': + $destination_offset_x = 0; + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + break; + case 'R': + case 'TR': + case 'BR': + $destination_offset_x = round($this->thumbnail_width - $this->thumbnail_image_width); + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + break; + case 'T': + case 'TL': + case 'TR': + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = 0; + break; + case 'B': + case 'BL': + case 'BR': + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = round($this->thumbnail_height - $this->thumbnail_image_height); + break; + case 'C': + default: + $destination_offset_x = round(($this->thumbnail_width - $this->thumbnail_image_width) / 2); + $destination_offset_y = round(($this->thumbnail_height - $this->thumbnail_image_height) / 2); + } + +// // copy/resize image to appropriate dimensions +// $borderThickness = 0; +// if (!empty($this->fltr)) { +// foreach ($this->fltr as $key => $value) { +// if (ereg('^bord\|([0-9]+)', $value, $matches)) { +// $borderThickness = $matches[1]; +// break; +// } +// } +// } +// if ($borderThickness > 0) { +// //$this->DebugMessage('Skipping ImageResizeFunction() because BorderThickness="'.$borderThickness.'"', __FILE__, __LINE__); +// $this->thumbnail_image_height /= 2; +// } + $this->ImageResizeFunction( + $this->gdimg_output, + $this->gdimg_source, + $destination_offset_x, + $destination_offset_y, + $this->thumbnailCropX, + $this->thumbnailCropY, + $this->thumbnail_image_width, + $this->thumbnail_image_height, + $this->thumbnailCropW, + $this->thumbnailCropH + ); + + $this->DebugMessage('memory_get_usage() after copy-resize = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); + ImageDestroy($this->gdimg_source); + $this->DebugMessage('memory_get_usage() after ImageDestroy = '.(function_exists('memory_get_usage') ? @memory_get_usage() : 'n/a'), __FILE__, __LINE__); + + $this->phpThumbDebug('8i'); + $this->AntiOffsiteLinking(); + $this->phpThumbDebug('8j'); + $this->ApplyFilters(); + $this->phpThumbDebug('8k'); + $this->AlphaChannelFlatten(); + $this->phpThumbDebug('8l'); + $this->MaxFileSize(); + $this->phpThumbDebug('8m'); + + $this->DebugMessage('GenerateThumbnail() completed successfully', __FILE__, __LINE__); + return true; + } + + + // public: + function RenderOutput() { + if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { + $this->DebugMessage('RenderOutput() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); + return false; + } + if (!$this->thumbnailFormat) { + $this->DebugMessage('RenderOutput() failed because $this->thumbnailFormat is empty', __FILE__, __LINE__); + return false; + } + if ($this->useRawIMoutput) { + $this->DebugMessage('RenderOutput copying $this->IMresizedData ('.strlen($this->IMresizedData).' bytes) to $this->outputImage', __FILE__, __LINE__); + $this->outputImageData = $this->IMresizedData; + return true; + } + + $builtin_formats = array(); + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + $builtin_formats['wbmp'] = (bool) ($imagetypes & IMG_WBMP); + $builtin_formats['jpg'] = (bool) ($imagetypes & IMG_JPG); + $builtin_formats['gif'] = (bool) ($imagetypes & IMG_GIF); + $builtin_formats['png'] = (bool) ($imagetypes & IMG_PNG); + } + $this->DebugMessage('RenderOutput() attempting Image'.strtoupper(@$this->thumbnailFormat).'($this->gdimg_output)', __FILE__, __LINE__); + ob_start(); + switch ($this->thumbnailFormat) { + case 'wbmp': + if (!@$builtin_formats['wbmp']) { + $this->DebugMessage('GD does not have required built-in support for WBMP output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + ImageJPEG($this->gdimg_output, null, $this->thumbnailQuality); + $this->outputImageData = ob_get_contents(); + break; + + case 'jpeg': + case 'jpg': // should be "jpeg" not "jpg" but just in case... + if (!@$builtin_formats['jpg']) { + $this->DebugMessage('GD does not have required built-in support for JPEG output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + ImageJPEG($this->gdimg_output, null, $this->thumbnailQuality); + $this->outputImageData = ob_get_contents(); + break; + + case 'png': + if (!@$builtin_formats['png']) { + $this->DebugMessage('GD does not have required built-in support for PNG output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + ImagePNG($this->gdimg_output); + $this->outputImageData = ob_get_contents(); + break; + + case 'gif': + if (!@$builtin_formats['gif']) { + $this->DebugMessage('GD does not have required built-in support for GIF output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + ImageGIF($this->gdimg_output); + $this->outputImageData = ob_get_contents(); + break; + + case 'bmp': + $ImageOutFunction = '"builtin BMP output"'; + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $phpthumb_bmp = new phpthumb_bmp(); + $this->outputImageData = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); + unset($phpthumb_bmp); + break; + + case 'ico': + $ImageOutFunction = '"builtin ICO output"'; + if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $phpthumb_ico = new phpthumb_ico(); + $arrayOfOutputImages = array($this->gdimg_output); + $this->outputImageData = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); + unset($phpthumb_ico); + break; + + default: + $this->DebugMessage('RenderOutput failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + ob_end_clean(); + if (!$this->outputImageData) { + $this->DebugMessage('RenderOutput() for "'.$this->thumbnailFormat.'" failed', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + $this->DebugMessage('RenderOutput() completing with $this->outputImageData = '.strlen($this->outputImageData).' bytes', __FILE__, __LINE__); + return true; + } + + function RenderToFile($filename) { + if (eregi('^(f|ht)tps?\://', $filename)) { + $this->DebugMessage('RenderToFile() failed because $filename ('.$filename.') is a URL', __FILE__, __LINE__); + return false; + } + // render thumbnail to this file only, do not cache, do not output to browser + //$renderfilename = $this->ResolveFilenameToAbsolute(dirname($filename)).DIRECTORY_SEPARATOR.basename($filename); + $renderfilename = $filename; + if (($filename{0} != '/') && ($filename{0} != '\\') && ($filename{1} != ':')) { + $renderfilename = $this->ResolveFilenameToAbsolute($renderfilename); + } + if (!@is_writable(dirname($renderfilename))) { + $this->DebugMessage('RenderToFile() failed because "'.dirname($renderfilename).'/" is not writable', __FILE__, __LINE__); + return false; + } + if (@is_file($renderfilename) && !@is_writable($renderfilename)) { + $this->DebugMessage('RenderToFile() failed because "'.$renderfilename.'" is not writable', __FILE__, __LINE__); + return false; + } + + if ($this->RenderOutput()) { + if (file_put_contents($renderfilename, $this->outputImageData)) { + $this->DebugMessage('RenderToFile('.$renderfilename.') succeeded', __FILE__, __LINE__); + return true; + } + if (!@file_exists($renderfilename)) { + $this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] did not appear to fail, but the output image does not exist either...', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('RenderOutput ['.$this->thumbnailFormat.'('.$renderfilename.')] failed', __FILE__, __LINE__); + } + return false; + } + + + // public: + function OutputThumbnail() { + if (!$this->useRawIMoutput && !is_resource($this->gdimg_output)) { + $this->DebugMessage('OutputThumbnail() failed because !is_resource($this->gdimg_output)', __FILE__, __LINE__); + return false; + } + if (headers_sent()) { + return $this->ErrorImage('OutputThumbnail() failed - headers already sent'); + exit; + } + + $downloadfilename = phpthumb_functions::SanitizeFilename(is_string($this->sia) ? $this->sia : ($this->down ? $this->down : 'phpThumb_generated_thumbnail'.'.'.$this->thumbnailFormat)); + $this->DebugMessage('Content-Disposition header filename set to "'.$downloadfilename.'"', __FILE__, __LINE__); + if ($downloadfilename) { + header('Content-Disposition: '.($this->down ? 'attachment' : 'inline').'; filename="'.$downloadfilename.'"'); + } else { + $this->DebugMessage('failed to send Content-Disposition header because $downloadfilename is empty', __FILE__, __LINE__); + } + + if ($this->useRawIMoutput) { + + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $this->IMresizedData; + + } else { + + $this->DebugMessage('ImageInterlace($this->gdimg_output, '.intval($this->config_output_interlace).')', __FILE__, __LINE__); + ImageInterlace($this->gdimg_output, intval($this->config_output_interlace)); + switch ($this->thumbnailFormat) { + case 'jpeg': + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + $ImageOutFunction = 'image'.$this->thumbnailFormat; + @$ImageOutFunction($this->gdimg_output, '', $this->thumbnailQuality); + break; + + case 'png': + case 'gif': + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + $ImageOutFunction = 'image'.$this->thumbnailFormat; + @$ImageOutFunction($this->gdimg_output); + break; + + case 'bmp': + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.bmp.php" which is required for BMP format output', __FILE__, __LINE__); + return false; + } + $phpthumb_bmp = new phpthumb_bmp(); + if (is_object($phpthumb_bmp)) { + $bmp_data = $phpthumb_bmp->GD2BMPstring($this->gdimg_output); + unset($phpthumb_bmp); + if (!$bmp_data) { + $this->DebugMessage('$phpthumb_bmp->GD2BMPstring() failed', __FILE__, __LINE__); + return false; + } + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $bmp_data; + } else { + $this->DebugMessage('new phpthumb_bmp() failed', __FILE__, __LINE__); + return false; + } + break; + + case 'ico': + if (!@include_once(dirname(__FILE__).'/phpthumb.ico.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.ico.php" which is required for ICO format output', __FILE__, __LINE__); + return false; + } + $phpthumb_ico = new phpthumb_ico(); + if (is_object($phpthumb_ico)) { + $arrayOfOutputImages = array($this->gdimg_output); + $ico_data = $phpthumb_ico->GD2ICOstring($arrayOfOutputImages); + unset($phpthumb_ico); + if (!$ico_data) { + $this->DebugMessage('$phpthumb_ico->GD2ICOstring() failed', __FILE__, __LINE__); + return false; + } + header('Content-Type: '.phpthumb_functions::ImageTypeToMIMEtype($this->thumbnailFormat)); + echo $ico_data; + } else { + $this->DebugMessage('new phpthumb_ico() failed', __FILE__, __LINE__); + return false; + } + break; + + default: + $this->DebugMessage('OutputThumbnail failed because $this->thumbnailFormat "'.$this->thumbnailFormat.'" is not valid', __FILE__, __LINE__); + return false; + break; + } + + } + return true; + } + + + // public: + function CleanUpCacheDirectory() { + if (($this->config_cache_maxage > 0) || ($this->config_cache_maxsize > 0) || ($this->config_cache_maxfiles > 0)) { + $CacheDirOldFilesAge = array(); + $CacheDirOldFilesSize = array(); + $AllFilesInCacheDirectory = phpthumb_functions::GetAllFilesInSubfolders($this->config_cache_directory); + foreach ($AllFilesInCacheDirectory as $fullfilename) { + if (eregi('^phpThumb_cache_', $fullfilename) && file_exists($fullfilename)) { + $CacheDirOldFilesAge[$fullfilename] = @fileatime($fullfilename); + if ($CacheDirOldFilesAge[$fullfilename] == 0) { + $CacheDirOldFilesAge[$fullfilename] = @filemtime($fullfilename); + } + $CacheDirOldFilesSize[$fullfilename] = @filesize($fullfilename); + } + } + if (empty($CacheDirOldFilesSize)) { + return true; + } + $DeletedKeys = array(); + foreach ($CacheDirOldFilesSize as $fullfilename => $filesize) { + // purge all zero-size files more than an hour old (to prevent trying to delete just-created and/or in-use files) + $cutofftime = time() - 3600; + if (($filesize == 0) && ($CacheDirOldFilesAge[$fullfilename] < $cutofftime)) { + if (@unlink($fullfilename)) { + $DeletedKeys[] = $fullfilename; + unset($CacheDirOldFilesSize[$fullfilename]); + unset($CacheDirOldFilesAge[$fullfilename]); + } + } + } + $this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys).' zero-byte files', __FILE__, __LINE__); + asort($CacheDirOldFilesAge); + + if ($this->config_cache_maxfiles > 0) { + $TotalCachedFiles = count($CacheDirOldFilesAge); + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) { + if ($TotalCachedFiles > $this->config_cache_maxfiles) { + if (@unlink($fullfilename)) { + $TotalCachedFiles--; + $DeletedKeys[] = $fullfilename; + } + } else { + // there are few enough files to keep the rest + break; + } + } + $this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys).' files based on (config_cache_maxfiles='.$this->config_cache_maxfiles.')', __FILE__, __LINE__); + foreach ($DeletedKeys as $fullfilename) { + unset($CacheDirOldFilesAge[$fullfilename]); + unset($CacheDirOldFilesSize[$fullfilename]); + } + } + + if ($this->config_cache_maxage > 0) { + $mindate = time() - $this->config_cache_maxage; + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) { + if ($filedate > 0) { + if ($filedate < $mindate) { + if (@unlink($fullfilename)) { + $DeletedKeys[] = $fullfilename; + } + } else { + // the rest of the files are new enough to keep + break; + } + } + } + $this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys).' files based on (config_cache_maxage='.$this->config_cache_maxage.')', __FILE__, __LINE__); + foreach ($DeletedKeys as $fullfilename) { + unset($CacheDirOldFilesAge[$fullfilename]); + unset($CacheDirOldFilesSize[$fullfilename]); + } + } + + if ($this->config_cache_maxsize > 0) { + $TotalCachedFileSize = array_sum($CacheDirOldFilesSize); + $DeletedKeys = array(); + foreach ($CacheDirOldFilesAge as $fullfilename => $filedate) { + if ($TotalCachedFileSize > $this->config_cache_maxsize) { + if (@unlink($fullfilename)) { + $TotalCachedFileSize -= $CacheDirOldFilesSize[$fullfilename]; + $DeletedKeys[] = $fullfilename; + } + } else { + // the total filesizes are small enough to keep the rest of the files + break; + } + } + $this->DebugMessage('CleanUpCacheDirectory() purged '.count($DeletedKeys).' files based on (config_cache_maxsize='.$this->config_cache_maxsize.')', __FILE__, __LINE__); + foreach ($DeletedKeys as $fullfilename) { + unset($CacheDirOldFilesAge[$fullfilename]); + unset($CacheDirOldFilesSize[$fullfilename]); + } + } + + } else { + $this->DebugMessage('skipping CleanUpCacheDirectory() because config set to not use it', __FILE__, __LINE__); + } + return true; + } + + ////////////////////////////////////////////////////////////////////// + + function ResolveSource() { + if (is_resource($this->gdimg_source)) { + $this->DebugMessage('ResolveSource() exiting because is_resource($this->gdimg_source)', __FILE__, __LINE__); + return true; + } + if ($this->rawImageData) { + $this->sourceFilename = null; + $this->DebugMessage('ResolveSource() exiting because $this->rawImageData is set ('.number_format(strlen($this->rawImageData)).' bytes)', __FILE__, __LINE__); + return true; + } + if ($this->sourceFilename) { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->sourceFilename); + $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'"', __FILE__, __LINE__); + } elseif ($this->src) { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); + $this->DebugMessage('$this->sourceFilename set to "'.$this->sourceFilename.'" from $this->src ('.$this->src.')', __FILE__, __LINE__); + } else { + return $this->ErrorImage('$this->sourceFilename and $this->src are both empty'); + } + if ($this->iswindows && ((substr($this->sourceFilename, 0, 2) == '//') || (substr($this->sourceFilename, 0, 2) == '\\\\'))) { + // Windows \\share\filename.ext + } elseif (eregi('^(f|ht)tps?\://', $this->sourceFilename)) { + // URL + if ($this->config_http_user_agent) { + ini_set('user_agent', $this->config_http_user_agent); + } + } elseif (!@file_exists($this->sourceFilename)) { + return $this->ErrorImage('"'.$this->sourceFilename.'" does not exist'); + } elseif (!@is_file($this->sourceFilename)) { + return $this->ErrorImage('"'.$this->sourceFilename.'" is not a file'); + } + return true; + } + + function setOutputFormat() { + static $alreadyCalled = false; + if ($this->thumbnailFormat && $alreadyCalled) { + return true; + } + $alreadyCalled = true; + + $AvailableImageOutputFormats = array(); + $AvailableImageOutputFormats[] = 'text'; + if (@is_readable(dirname(__FILE__).'/phpthumb.ico.php')) { + $AvailableImageOutputFormats[] = 'ico'; + } + if (@is_readable(dirname(__FILE__).'/phpthumb.bmp.php')) { + $AvailableImageOutputFormats[] = 'bmp'; + } + + $this->thumbnailFormat = 'ico'; + + // Set default output format based on what image types are available + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_WBMP) { + $this->thumbnailFormat = 'wbmp'; + $AvailableImageOutputFormats[] = 'wbmp'; + } + if ($imagetypes & IMG_GIF) { + $this->thumbnailFormat = 'gif'; + $AvailableImageOutputFormats[] = 'gif'; + } + if ($imagetypes & IMG_PNG) { + $this->thumbnailFormat = 'png'; + $AvailableImageOutputFormats[] = 'png'; + } + if ($imagetypes & IMG_JPG) { + $this->thumbnailFormat = 'jpeg'; + $AvailableImageOutputFormats[] = 'jpeg'; + } + } else { + //return $this->ErrorImage('ImageTypes() does not exist - GD support might not be enabled?'); + $this->DebugMessage('ImageTypes() does not exist - GD support might not be enabled?', __FILE__, __LINE__); + } + if ($this->ImageMagickVersion()) { + $IMformats = array('jpeg', 'png', 'gif', 'bmp', 'ico', 'wbmp'); + $this->DebugMessage('Addding ImageMagick formats to $AvailableImageOutputFormats ('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); + foreach ($IMformats as $key => $format) { + $AvailableImageOutputFormats[] = $format; + } + } + $AvailableImageOutputFormats = array_unique($AvailableImageOutputFormats); + $this->DebugMessage('$AvailableImageOutputFormats = array('.implode(';', $AvailableImageOutputFormats).')', __FILE__, __LINE__); + + if (strtolower($this->config_output_format) == 'jpg') { + $this->config_output_format = 'jpeg'; + } + if (strtolower($this->f) == 'jpg') { + $this->f = 'jpeg'; + } + if (phpthumb_functions::CaseInsensitiveInArray($this->config_output_format, $AvailableImageOutputFormats)) { + // set output format to config default if that format is available + $this->DebugMessage('$this->thumbnailFormat set to $this->config_output_format "'.strtolower($this->config_output_format).'"', __FILE__, __LINE__); + $this->thumbnailFormat = strtolower($this->config_output_format); + } elseif ($this->config_output_format) { + $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->config_output_format ('.strtolower($this->config_output_format).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); + } + if ($this->f && (phpthumb_functions::CaseInsensitiveInArray($this->f, $AvailableImageOutputFormats))) { + // override output format if $this->f is set and that format is available + $this->DebugMessage('$this->thumbnailFormat set to $this->f "'.strtolower($this->f).'"', __FILE__, __LINE__); + $this->thumbnailFormat = strtolower($this->f); + } elseif ($this->f) { + $this->DebugMessage('$this->thumbnailFormat staying as "'.$this->thumbnailFormat.'" because $this->f ('.strtolower($this->f).') is not in $AvailableImageOutputFormats', __FILE__, __LINE__); + } + + // for JPEG images, quality 1 (worst) to 99 (best) + // quality < 25 is nasty, with not much size savings - not recommended + // problems with 100 - invalid JPEG? + $this->thumbnailQuality = max(1, min(99, ($this->q ? $this->q : 75))); + $this->DebugMessage('$this->thumbnailQuality set to "'.$this->thumbnailQuality.'"', __FILE__, __LINE__); + + return true; + } + + function setCacheDirectory() { + // resolve cache directory to absolute pathname + $this->DebugMessage('setCacheDirectory() starting with config_cache_directory = "'.$this->config_cache_directory.'"', __FILE__, __LINE__); + if (substr($this->config_cache_directory, 0, 1) == '.') { + if (eregi('^(f|ht)tps?\://', $this->src)) { + if (!$this->config_cache_disable_warning) { + $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') cannot be used for remote images. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); + } + } elseif ($this->src) { + // resolve relative cache directory to source image + $this->config_cache_directory = dirname($this->ResolveFilenameToAbsolute($this->src)).DIRECTORY_SEPARATOR.$this->config_cache_directory; + } else { + // $this->new is probably set + } + } + if (substr($this->config_cache_directory, -1) == '/') { + $this->config_cache_directory = substr($this->config_cache_directory, 0, -1); + } + if ($this->iswindows) { + $this->config_cache_directory = str_replace('/', DIRECTORY_SEPARATOR, $this->config_cache_directory); + } + if ($this->config_cache_directory) { + $real_cache_path = realpath($this->config_cache_directory); + if (!$real_cache_path) { + $this->DebugMessage('realpath($this->config_cache_directory) failed for "'.$this->config_cache_directory.'"', __FILE__, __LINE__); + if (!is_dir($this->config_cache_directory)) { + $this->DebugMessage('!is_dir('.$this->config_cache_directory.')', __FILE__, __LINE__); + } + } + if ($real_cache_path) { + $this->DebugMessage('setting config_cache_directory to realpath('.$this->config_cache_directory.') = "'.$real_cache_path.'"', __FILE__, __LINE__); + $this->config_cache_directory = $real_cache_path; + } + } + if (!is_dir($this->config_cache_directory)) { + if (!$this->config_cache_disable_warning) { + $this->ErrorImage('$this->config_cache_directory ('.$this->config_cache_directory.') does not exist. Adjust "cache_directory" or "cache_disable_warning" in phpThumb.config.php'); + } + $this->DebugMessage('$this->config_cache_directory ('.$this->config_cache_directory.') is not a directory', __FILE__, __LINE__); + $this->config_cache_directory = null; + } elseif (!@is_writable($this->config_cache_directory)) { + $this->DebugMessage('$this->config_cache_directory is not writable ('.$this->config_cache_directory.')', __FILE__, __LINE__); + } + + if (!@is_dir($this->config_temp_directory) && !@is_writable($this->config_temp_directory) && @is_dir($this->config_cache_directory) && @is_writable($this->config_cache_directory)) { + $this->DebugMessage('setting $this->config_temp_directory = $this->config_cache_directory ('.$this->config_cache_directory.')', __FILE__, __LINE__); + $this->config_temp_directory = $this->config_cache_directory; + } + return true; + } + + + function ResolveFilenameToAbsolute($filename) { + if (!$filename) { + return false; + } + + //if (eregi('^(f|ht)tps?\://', $filename)) { + if (eregi('^[a-z0-9]+\:/{1,2}', $filename)) { + // eg: http://host/path/file.jpg (HTTP URL) + // eg: ftp://host/path/file.jpg (FTP URL) + // eg: data1:/path/file.jpg (Netware path) + + //$AbsoluteFilename = $filename; + return $filename; + + } elseif ($this->iswindows && ($filename{1} == ':')) { + + // absolute pathname (Windows) + $AbsoluteFilename = $filename; + + } elseif ($this->iswindows && ((substr($filename, 0, 2) == '//') || (substr($filename, 0, 2) == '\\\\'))) { + + // absolute pathname (Windows) + $AbsoluteFilename = $filename; + + } elseif ($filename{0} == '/') { + + if (@is_readable($filename) && !@is_readable($this->config_document_root.$filename)) { + + // absolute filename (*nix) + $AbsoluteFilename = $filename; + + } elseif ($filename{1} == '~') { + + // /~user/path + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray($filename)) { + $AbsoluteFilename = $ApacheLookupURIarray['filename']; + } else { + $AbsoluteFilename = realpath($filename); + if (@is_readable($AbsoluteFilename)) { + $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath($filename)', __FILE__, __LINE__); + } else { + return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.$filename.'". This has been known to fail on Apache2 - try using the absolute filename for the source image (ex: "/home/user/httpdocs/image.jpg" instead of "/~user/image.jpg")'); + } + } + + } else { + + // relative filename (any OS) + if (ereg('^'.preg_quote($this->config_document_root), $filename)) { + $AbsoluteFilename = $filename; + $this->DebugMessage('ResolveFilenameToAbsolute() NOT prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); + } else { + $AbsoluteFilename = $this->config_document_root.$filename; + $this->DebugMessage('ResolveFilenameToAbsolute() prepending $this->config_document_root ('.$this->config_document_root.') to $filename ('.$filename.') resulting in ($AbsoluteFilename = "'.$AbsoluteFilename.'")', __FILE__, __LINE__); + } + + } + + } else { + + // relative to current directory (any OS) + $AbsoluteFilename = $this->config_document_root.dirname(@$_SERVER['PHP_SELF']).DIRECTORY_SEPARATOR.$filename; + //if (!@file_exists($AbsoluteFilename) && @file_exists(realpath($this->DotPadRelativeDirectoryPath($filename)))) { + // $AbsoluteFilename = realpath($this->DotPadRelativeDirectoryPath($filename)); + //} + + if (substr(dirname(@$_SERVER['PHP_SELF']), 0, 2) == '/~') { + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { + $AbsoluteFilename = $ApacheLookupURIarray['filename'].DIRECTORY_SEPARATOR.$filename; + } else { + $AbsoluteFilename = realpath('.').DIRECTORY_SEPARATOR.$filename; + if (@is_readable($AbsoluteFilename)) { + $this->DebugMessage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'", but the correct filename ('.$AbsoluteFilename.') seems to have been resolved with realpath(.)/$filename', __FILE__, __LINE__); + } else { + return $this->ErrorImage('phpthumb_functions::ApacheLookupURIarray() failed for "'.dirname(@$_SERVER['PHP_SELF']).'". This has been known to fail on Apache2 - try using the absolute filename for the source image'); + } + } + } + + } + if (is_link($AbsoluteFilename)) { + $this->DebugMessage('is_link()==true, changing "'.$AbsoluteFilename.'" to "'.readlink($AbsoluteFilename).'"', __FILE__, __LINE__); + $AbsoluteFilename = readlink($AbsoluteFilename); + } + if (realpath($AbsoluteFilename)) { + $AbsoluteFilename = realpath($AbsoluteFilename); + } + if ($this->iswindows) { + $AbsoluteFilename = eregi_replace('^'.preg_quote(realpath($this->config_document_root)), realpath($this->config_document_root), $AbsoluteFilename); + $AbsoluteFilename = str_replace(DIRECTORY_SEPARATOR, '/', $AbsoluteFilename); + } + if (!$this->config_allow_src_above_docroot && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', realpath($this->config_document_root))), $AbsoluteFilename)) { + $this->DebugMessage('!$this->config_allow_src_above_docroot therefore setting "'.$AbsoluteFilename.'" (outside "'.realpath($this->config_document_root).'") to null', __FILE__, __LINE__); + return false; + } + if (!$this->config_allow_src_above_phpthumb && !ereg('^'.preg_quote(str_replace(DIRECTORY_SEPARATOR, '/', dirname(__FILE__))), $AbsoluteFilename)) { + $this->DebugMessage('!$this->config_allow_src_above_phpthumb therefore setting "'.$AbsoluteFilename.'" (outside "'.dirname(__FILE__).'") to null', __FILE__, __LINE__); + return false; + } + return $AbsoluteFilename; + } + + function ImageMagickWhichConvert() { + static $WhichConvert = null; + if (is_null($WhichConvert)) { + if ($this->iswindows) { + $WhichConvert = false; + } else { + $WhichConvert = trim(phpthumb_functions::SafeExec('which convert')); + } + } + return $WhichConvert; + } + + function ImageMagickCommandlineBase() { + static $commandline = null; + if (is_null($commandline)) { + $commandline = (!is_null($this->config_imagemagick_path) ? $this->config_imagemagick_path : ''); + + if ($this->config_imagemagick_path && ($this->config_imagemagick_path != realpath($this->config_imagemagick_path))) { + if (@is_executable(realpath($this->config_imagemagick_path))) { + $this->DebugMessage('Changing $this->config_imagemagick_path ('.$this->config_imagemagick_path.') to realpath($this->config_imagemagick_path) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); + $this->config_imagemagick_path = realpath($this->config_imagemagick_path); + } else { + $this->DebugMessage('Leaving $this->config_imagemagick_path as ('.$this->config_imagemagick_path.') because !is_execuatable(realpath($this->config_imagemagick_path)) ('.realpath($this->config_imagemagick_path).')', __FILE__, __LINE__); + } + } + $this->DebugMessage(' file_exists('.$this->config_imagemagick_path.') = '.intval( @file_exists($this->config_imagemagick_path)), __FILE__, __LINE__); + $this->DebugMessage('is_executable('.$this->config_imagemagick_path.') = '.intval(@is_executable($this->config_imagemagick_path)), __FILE__, __LINE__); + if (@file_exists($this->config_imagemagick_path)) { + $this->DebugMessage('using ImageMagick path from $this->config_imagemagick_path ('.$this->config_imagemagick_path.')', __FILE__, __LINE__); + if ($this->iswindows) { + $commandline = substr($this->config_imagemagick_path, 0, 2).' && cd "'.str_replace('/', DIRECTORY_SEPARATOR, substr(dirname($this->config_imagemagick_path), 2)).'" && '.basename($this->config_imagemagick_path); + } else { + $commandline = '"'.$this->config_imagemagick_path.'"'; + } + return $commandline; + } + + $which_convert = $this->ImageMagickWhichConvert(); + $IMversion = $this->ImageMagickVersion(); + + if ($which_convert && ($which_convert{0} == '/') && @file_exists($which_convert)) { + + // `which convert` *should* return the path if "convert" exist, or nothing if it doesn't + // other things *may* get returned, like "sh: convert: not found" or "no convert in /usr/local/bin /usr/sbin /usr/bin /usr/ccs/bin" + // so only do this if the value returned exists as a file + $this->DebugMessage('using ImageMagick path from `which convert` ('.$which_convert.')', __FILE__, __LINE__); + $commandline = 'convert'; + + } elseif ($IMversion) { + + $this->DebugMessage('setting ImageMagick path to $this->config_imagemagick_path ('.$this->config_imagemagick_path.') ['.$IMversion.']', __FILE__, __LINE__); + $commandline = $this->config_imagemagick_path; + + } else { + + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because cannot find convert in $this->config_imagemagick_path ('.$this->config_imagemagick_path.'), and `which convert` returned ('.$which_convert.')', __FILE__, __LINE__); + $commandline = ''; + + } + } + return $commandline; + } + + function ImageMagickVersion($returnRAW=false) { + static $versionstring = null; + if (is_null($versionstring)) { + $commandline = $this->ImageMagickCommandlineBase(); + $commandline = (!is_null($commandline) ? $commandline : ''); + + $versionstring = array(0=>'', 1=>''); + if ($commandline) { + $commandline .= ' --version'; + $this->DebugMessage('ImageMagick version checked with "'.$commandline.'"', __FILE__, __LINE__); + $versionstring[1] = trim(phpthumb_functions::SafeExec($commandline)); + if (eregi('^Version: [^0-9]*([ 0-9\\.\\:Q/]+) (http|file)\:', $versionstring[1], $matches)) { + $versionstring[0] = $matches[1]; + } else { + $versionstring[0] = false; + $this->DebugMessage('ImageMagick did not return recognized version string ('.$versionstring[1].')', __FILE__, __LINE__); + } + $this->DebugMessage('ImageMagick convert --version says "'.$matches[0].'"', __FILE__, __LINE__); + } + } + return @$versionstring[intval($returnRAW)]; + } + + function ImageMagickSwitchAvailable($switchname) { + static $IMoptions = null; + if (is_null($IMoptions)) { + $IMoptions = array(); + $commandline = $this->ImageMagickCommandlineBase(); + if (!is_null($commandline)) { + $commandline .= ' -help'; + $IMhelp_lines = explode("\n", phpthumb_functions::SafeExec($commandline)); + foreach ($IMhelp_lines as $line) { + if (ereg('^[\+\-]([a-z\-]+) ', trim($line), $matches)) { + $IMoptions[$matches[1]] = true; + } + } + } + } + if (is_array($switchname)) { + $allOK = true; + foreach ($switchname as $key => $value) { + if (!isset($IMoptions[$value])) { + $allOK = false; + break; + } + } + $this->DebugMessage('ImageMagickSwitchAvailable('.implode(';', $switchname).') = '.intval($allOK).'', __FILE__, __LINE__); + } else { + $allOK = isset($IMoptions[$switchname]); + $this->DebugMessage('ImageMagickSwitchAvailable('.$switchname.') = '.intval($allOK).'', __FILE__, __LINE__); + } + return $allOK; + } + + function ImageMagickFormatsList() { + static $IMformatsList = null; + if (is_null($IMformatsList)) { + $IMformatsList = ''; + $commandline = $this->ImageMagickCommandlineBase(); + if (!is_null($commandline)) { + $commandline = dirname($commandline).DIRECTORY_SEPARATOR.str_replace('convert', 'identify', basename($commandline)); + $commandline .= ' -list format'; + $IMformatsList = phpthumb_functions::SafeExec($commandline); + } + } + return $IMformatsList; + } + + function ImageMagickThumbnailToGD() { + // http://www.imagemagick.org/script/command-line-options.php + + $this->useRawIMoutput = true; + if (phpthumb_functions::gd_version()) { + //$UnAllowedParameters = array('sx', 'sy', 'sw', 'sh', 'xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); + $UnAllowedParameters = array('xto', 'ra', 'ar', 'bg', 'bc', 'fltr'); + foreach ($UnAllowedParameters as $parameter) { + if (isset($this->$parameter)) { + $this->DebugMessage('$this->useRawIMoutput=false because "'.$parameter.'" is set', __FILE__, __LINE__); + $this->useRawIMoutput = false; + break; + } + } + } + $outputFormat = $this->thumbnailFormat; + if (phpthumb_functions::gd_version()) { + if ($this->useRawIMoutput) { + switch ($this->thumbnailFormat) { + case 'gif': + $ImageCreateFunction = 'ImageCreateFromGIF'; + $this->is_alpha = true; + break; + case 'png': + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + break; + case 'jpg': + case 'jpeg': + $ImageCreateFunction = 'ImageCreateFromJPEG'; + break; + default: + $outputFormat = 'png'; + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + $this->useRawIMoutput = false; + break; + } + if (!function_exists(@$ImageCreateFunction)) { + // ImageMagickThumbnailToGD() depends on ImageCreateFromPNG/ImageCreateFromGIF + //$this->DebugMessage('ImageMagickThumbnailToGD() aborting because '.@$ImageCreateFunction.'() is not available', __FILE__, __LINE__); + $this->useRawIMoutput = true; + //return false; + } + } else { + $outputFormat = 'png'; + $ImageCreateFunction = 'ImageCreateFromPNG'; + $this->is_alpha = true; + $this->useRawIMoutput = false; + } + } + + // http://freealter.org/doc_distrib/ImageMagick-5.1.1/www/convert.html + if (!$this->sourceFilename) { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because $this->sourceFilename is empty', __FILE__, __LINE__); + $this->useRawIMoutput = false; + return false; + } + if (ini_get('safe_mode')) { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because safe_mode is enabled', __FILE__, __LINE__); + $this->useRawIMoutput = false; + return false; + } + + $commandline = $this->ImageMagickCommandlineBase(); + if ($commandline) { + if ($IMtempfilename = $this->phpThumb_tempnam()) { + $IMtempfilename = realpath($IMtempfilename); + + $IMuseExplicitImageOutputDimensions = false; + if ($this->ImageMagickSwitchAvailable('thumbnail') && $this->config_imagemagick_use_thumbnail) { + $IMresizeParameter = 'thumbnail'; + } else { + $IMresizeParameter = 'resize'; + + // some (older? around 2002) versions of IM won't accept "-resize 100x" but require "-resize 100x100" + $commandline_test = $this->ImageMagickCommandlineBase().' logo: -resize 1x "'.$IMtempfilename.'" 2>&1'; + $IMresult_test = phpthumb_functions::SafeExec($commandline_test); + $IMuseExplicitImageOutputDimensions = eregi('image dimensions are zero', $IMresult_test); + $this->DebugMessage('IMuseExplicitImageOutputDimensions = '.intval($IMuseExplicitImageOutputDimensions), __FILE__, __LINE__); + if ($fp_im_temp = @fopen($IMtempfilename, 'wb')) { + // erase temp image so ImageMagick logo doesn't get output if other processing fails + fclose($fp_im_temp); + } + } + + + if (!is_null($this->dpi) && $this->ImageMagickSwitchAvailable('modulate')) { + // for raster source formats only (WMF, PDF, etc) + $commandline .= ' -density '.$this->dpi; + } + ob_start(); + $getimagesize = GetImageSize($this->sourceFilename); + $GetImageSizeError = ob_get_contents(); + ob_end_clean(); + if (is_array($getimagesize)) { + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') SUCCEEDED: '.serialize($getimagesize), __FILE__, __LINE__); + } else { + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') FAILED with error "'.$GetImageSizeError.'"', __FILE__, __LINE__); + } + if (is_array($getimagesize)) { + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') returned [w='.$getimagesize[0].';h='.$getimagesize[1].';f='.$getimagesize[2].']', __FILE__, __LINE__); + $this->source_width = $getimagesize[0]; + $this->source_height = $getimagesize[1]; + $this->DebugMessage('source dimensions set to '.$this->source_width.'x'.$this->source_height, __FILE__, __LINE__); + $this->SetOrientationDependantWidthHeight(); + + if (!eregi('('.implode('|', $this->AlphaCapableFormats).')', $outputFormat)) { + // not a transparency-capable format + $commandline .= ' -background "#'.($this->bg ? $this->bg : 'FFFFFF').'"'; + if ($getimagesize[2] == 1) { + $commandline .= ' -flatten'; + } + } + if ($getimagesize[2] == 1) { + $commandline .= ' -coalesce'; // may be needed for animated GIFs + } + if ($this->source_width || $this->source_height) { + if ($this->zc) { + + $borderThickness = 0; + if (!empty($this->fltr)) { + foreach ($this->fltr as $key => $value) { + if (ereg('^bord\|([0-9]+)', $value, $matches)) { + $borderThickness = $matches[1]; + break; + } + } + } + $wAll = intval(max($this->w, $this->wp, $this->wl, $this->ws)) - (2 * $borderThickness); + $hAll = intval(max($this->h, $this->hp, $this->hl, $this->hs)) - (2 * $borderThickness); + $imAR = $this->source_width / $this->source_height; + //$zcAR = (($wAll && $hAll) ? $wAll / $hAll : $imAR); + $zcAR = (($wAll && $hAll) ? $wAll / $hAll : 1); +//echo '
    ';
    +//var_dump($wAll);
    +//var_dump($hAll);
    +//var_dump($zcAR);
    +							//if (($wAll > $borderThickness) && ($wAll > $borderThickness)) {
    +							//	$zcAR = ($wAll - (2 * $borderThickness)) / ($hAll - (2 * $borderThickness));
    +							//}
    +//echo ($wAll - (2 * $borderThickness))."\n";
    +//echo ($hAll - (2 * $borderThickness))."\n";
    +//var_dump($zcAR);
    +							$side  = phpthumb_functions::nonempty_min($this->source_width, $this->source_height, max($wAll, $hAll));
    +							$sideX = phpthumb_functions::nonempty_min($this->source_width,                       $wAll, round($hAll * $zcAR));
    +							$sideY = phpthumb_functions::nonempty_min(                     $this->source_height, $hAll, round($wAll / $zcAR));
    +
    +							$thumbnailH = round(max($sideY, ($sideY * $zcAR) / $imAR));
    +							if ($IMuseExplicitImageOutputDimensions) {
    +								$commandline .= ' -'.$IMresizeParameter.' '.$thumbnailH.'x'.$thumbnailH;
    +							} else {
    +								$commandline .= ' -'.$IMresizeParameter.' x'.$thumbnailH;
    +							}
    +//echo '
    ';
    +//var_dump($this->w);
    +//var_dump($this->wp);
    +//var_dump($this->wl);
    +//var_dump($this->ws);
    +//var_dump($wAll);
    +//var_dump($side);
    +//var_dump($sideX);
    +//var_dump($sideY);
    +//var_dump($zcAR);
    +//var_dump($thumbnailH);
    +//print_r($getimagesize);
    +//echo '
    '; + + $commandline .= ' -gravity center'; + + if (($wAll > 0) && ($hAll > 0)) { + $commandline .= ' -crop '.$wAll.'x'.$hAll.'+0+0'; + } else { + $commandline .= ' -crop '.$side.'x'.$side.'+0+0'; + } + if ($this->ImageMagickSwitchAvailable('repage')) { + $commandline .= ' +repage'; + } else { + $this->DebugMessage('Skipping "+repage" because ImageMagick (v'.$this->ImageMagickVersion().') does not support it', __FILE__, __LINE__); + } + + } elseif ($this->sw || $this->sh || $this->sx || $this->sy) { + + $commandline .= ' -crop '.($this->sw ? $this->sw : $this->source_width).'x'.($this->sh ? $this->sh : $this->source_height).'+'.$this->sx.'+'.$this->sy; + // this is broken for aoe=1, but unsure how to fix. Send advice to info@silisoftware.com + if ($this->w || $this->h) { + if ($this->ImageMagickSwitchAvailable('repage')) { + $commandline .= ' -repage'; + } else { + $this->DebugMessage('Skipping "-repage" because ImageMagick (v'.$this->ImageMagickVersion().') does not support it', __FILE__, __LINE__); + } + if ($IMuseExplicitImageOutputDimensions) { + if ($this->w && !$this->h) { + $this->h = ceil($this->w / ($this->source_width / $this->source_height)); + } elseif ($this->h && !$this->w) { + $this->w = ceil($this->h * ($this->source_width / $this->source_height)); + } + } + $commandline .= ' -'.$IMresizeParameter.' '.$this->w.'x'.$this->h; + } + + } else { + + if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { + $commandline .= ' -'.$IMresizeParameter.' '.$this->w.'x'.$this->h.'!'; + } else { +//echo '
    ';
    +//print_r($getimagesize);
    +//echo '
    '; +//echo $this->w.'x'.$this->h.'
    '; + $this->w = ((($this->aoe || $this->far) && $this->w) ? $this->w : ($this->w ? phpthumb_functions::nonempty_min($this->w, $getimagesize[0]) : '')); + $this->h = ((($this->aoe || $this->far) && $this->h) ? $this->h : ($this->h ? phpthumb_functions::nonempty_min($this->h, $getimagesize[1]) : '')); +//echo $this->w.'x'.$this->h.'
    '; + if ($this->w || $this->h) { + if ($IMuseExplicitImageOutputDimensions) { + if ($this->w && !$this->h) { + $this->h = ceil($this->w / ($this->source_width / $this->source_height)); + } elseif ($this->h && !$this->w) { + $this->w = ceil($this->h * ($this->source_width / $this->source_height)); + } + } + $commandline .= ' -'.$IMresizeParameter.' '.$this->w.'x'.$this->h; + } + } + } + } + + } else { + + $this->DebugMessage('GetImageSize('.$this->sourceFilename.') failed', __FILE__, __LINE__); + if ($this->w || $this->h) { + if ($IMuseExplicitImageOutputDimensions) { + // unknown source aspect ration, just put large number and hope IM figures it out + $commandline .= ' -'.$IMresizeParameter.' '.($this->w ? $this->w : '9999').'x'.($this->h ? $this->h : '9999'); + } else { + $commandline .= ' -'.$IMresizeParameter.' '.$this->w.'x'.$this->h; + } + if ($this->iar && (intval($this->w) > 0) && (intval($this->h) > 0)) { + $commandline .= '!'; + } + } + + } + foreach ($this->fltr as $filterkey => $filtercommand) { + @list($command, $parameter) = explode('|', $filtercommand, 2); + switch ($command) { + case 'brit': + if ($this->ImageMagickSwitchAvailable('modulate')) { + $commandline .= ' -modulate '.(100 + $parameter).',100,100'; + unset($this->fltr[$filterkey]); + } + break; + + case 'cont': + if ($this->ImageMagickSwitchAvailable('contrast')) { + $contDiv10 = round($parameter / 10); + if ($contDiv10 > 0) { + for ($i = 0; $i < $contDiv10; $i++) { + $commandline .= ' -contrast'; // increase contrast by 10% + } + } elseif ($contDiv10 < 0) { + for ($i = $contDiv10; $i < 0; $i++) { + $commandline .= ' +contrast'; // decrease contrast by 10% + } + } else { + // do nothing + } + unset($this->fltr[$filterkey]); + } + break; + + case 'ds': + if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { + if ($parameter == 100) { + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + } else { + $commandline .= ' -modulate 100,'.(100 - $parameter).',100'; + } + unset($this->fltr[$filterkey]); + } + break; + + case 'sat': + if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { + if ($parameter == -100) { + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + } else { + $commandline .= ' -modulate 100,'.(100 + $parameter).',100'; + } + unset($this->fltr[$filterkey]); + } + break; + + case 'gray': + if ($this->ImageMagickSwitchAvailable(array('colorspace', 'modulate'))) { + $commandline .= ' -colorspace GRAY -modulate 100,0,100'; + //$commandline .= ' -colorspace GRAY'; + unset($this->fltr[$filterkey]); + } + break; + + case 'clr': + if ($this->ImageMagickSwitchAvailable(array('fill', 'colorize'))) { + @list($amount, $color) = explode('|', $parameter); + $commandline .= ' -fill #'.$color.' -colorize '.$amount; + } + break; + + case 'sep': + if ($this->ImageMagickSwitchAvailable('sepia-tone')) { + @list($amount, $color) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + if (!$color) { + $commandline .= ' -sepia-tone '.$amount.'%'; + unset($this->fltr[$filterkey]); + } + } + break; + + case 'gam': + if ($this->ImageMagickSwitchAvailable('gamma')) { + $commandline .= ' -gamma '.$parameter; + unset($this->fltr[$filterkey]); + } + break; + + case 'neg': + if ($this->ImageMagickSwitchAvailable('negate')) { + $commandline .= ' -negate'; + unset($this->fltr[$filterkey]); + } + break; + + case 'th': + if ($this->ImageMagickSwitchAvailable(array('threshold', 'dither', 'monochrome'))) { + $commandline .= ' -threshold '.round($parameter / 2.55).'% -dither -monochrome'; + unset($this->fltr[$filterkey]); + } + break; + + case 'rcd': + if ($this->ImageMagickSwitchAvailable(array('colors', 'dither'))) { + @list($colors, $dither) = explode('|', $parameter); + $colors = ($colors ? (int) $colors : 256); + $dither = ((strlen($dither) > 0) ? (bool) $dither : true); + $commandline .= ' -colors '.max($colors, 8); // ImageMagick will otherwise fail with "cannot quantize to fewer than 8 colors" + $commandline .= ($dither ? ' -dither' : ' +dither'); + unset($this->fltr[$filterkey]); + } + break; + + case 'flip': + if ($this->ImageMagickSwitchAvailable(array('flip', 'flop'))) { + if (strpos(strtolower($parameter), 'x') !== false) { + $commandline .= ' -flop'; + } + if (strpos(strtolower($parameter), 'y') !== false) { + $commandline .= ' -flip'; + } + unset($this->fltr[$filterkey]); + } + break; + + case 'edge': + if ($this->ImageMagickSwitchAvailable('edge')) { + $parameter = ($parameter ? $parameter : 2); + $commandline .= ' -edge '.($parameter ? $parameter : 1); + unset($this->fltr[$filterkey]); + } + break; + + case 'emb': + if ($this->ImageMagickSwitchAvailable(array('emboss', 'negate'))) { + $parameter = ($parameter ? $parameter : 2); + $commandline .= ' -emboss '.$parameter; + if ($parameter < 2) { + $commandline .= ' -negate'; // ImageMagick negates the image for some reason with '-emboss 1'; + } + unset($this->fltr[$filterkey]); + } + break; + + case 'lvl': + @list($band, $method, $threshold) = explode('|', $parameter); + $band = ($band ? ereg_replace('[^RGBA\\*]', '', strtoupper($band)) : '*'); + $method = ((strlen($method) > 0) ? intval($method) : 2); + $threshold = ((strlen($threshold) > 0) ? floatval($threshold) : 0.1); + + $band = ereg_replace('[^RGBA\\*]', '', strtoupper($band)); + + if (($method > 1) && !$this->ImageMagickSwitchAvailable(array('channel', 'contrast-stretch'))) { + // Because ImageMagick processing happens before PHP-GD filters, and because some + // clipping is involved in the "lvl" filter, if "lvl" happens before "wb" then the + // "wb" filter will have (almost) no effect. Therefore, if "wb" is enabled then + // force the "lvl" filter to be processed by GD, not ImageMagick. + foreach ($this->fltr as $fltr_key => $fltr_value) { + list($fltr_cmd) = explode('|', $fltr_value); + if ($fltr_cmd == 'wb') { + $this->DebugMessage('Setting "lvl" filter method to "0" (from "'.$method.'") because white-balance filter also enabled', __FILE__, __LINE__); + $method = 0; + } + } + } + + switch ($method) { + case 0: // internal RGB + case 1: // internal grayscale + break; + case 2: // ImageMagick "contrast-stretch" + if ($this->ImageMagickSwitchAvailable('contrast-stretch')) { + $thiscommand = ' -contrast-stretch '.$threshold.'%'; + $commandline .= (($band == '*') ? $thiscommand : ' -channel '.strtoupper($band).$thiscommand.' +channel'); + unset($this->fltr[$filterkey]); + } + break; + case 3: // ImageMagick "normalize" + if ($this->ImageMagickSwitchAvailable('normalize')) { + $thiscommand = ' -normalize'; + $commandline .= (($band == '*') ? $thiscommand : ' -channel '.strtoupper($band).$thiscommand.' +channel'); + unset($this->fltr[$filterkey]); + } + break; + default: + $this->DebugMessage('unsupported method ('.$method.') for "lvl" filter', __FILE__, __LINE__); + break; + } + if (isset($this->fltr[$filterkey]) && ($method > 1)) { + $this->fltr[$filterkey] = $command.'|'.$band.'|0|'.$threshold; + $this->DebugMessage('filter "lvl" remapped from method "'.$method.'" to method "0" because ImageMagick support is missing', __FILE__, __LINE__); + } + break; + + case 'wb': + if ($this->ImageMagickSwitchAvailable(array('channel', 'contrast-stretch'))) { + @list($threshold) = explode('|', $parameter); + $threshold = (is_float($threshold) ? $threshold : 0.1); + $commandline .= ' -channel R -contrast-stretch '.$threshold.'%'; + $commandline .= ' -channel G -contrast-stretch '.$threshold.'%'; + $commandline .= ' -channel B -contrast-stretch '.$threshold.'%'; + $commandline .= ' +channel'; + unset($this->fltr[$filterkey]); + } + break; + + case 'blur': + if ($this->ImageMagickSwitchAvailable('blur')) { + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + $commandline .= ' -blur '.$radius; + unset($this->fltr[$filterkey]); + } + break; + + case 'gblr': + if ($this->ImageMagickSwitchAvailable('gaussian')) { + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + $commandline .= ' -gaussian '.$radius; + unset($this->fltr[$filterkey]); + } + break; + + case 'usm': + if ($this->ImageMagickSwitchAvailable('unsharp')) { + @list($amount, $radius, $threshold) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + $radius = ($radius ? $radius : 0.5); + $threshold = (strlen($threshold) ? $threshold : 3); + $commandline .= ' -unsharp '.number_format(($radius * 2) - 1, 2).'x1+'.number_format($amount / 100, 2).'+'.number_format($threshold / 100, 2); + unset($this->fltr[$filterkey]); + } + break; + + case 'bord': + if ($this->ImageMagickSwitchAvailable(array('border', 'bordercolor', 'thumbnail', 'crop'))) { + if (!$this->zc) { + @list($width, $rX, $rY, $color) = explode('|', $parameter); + if ($width && !$rX && !$rY) { + if (!phpthumb_functions::IsHexColor($color)) { + $color = ($this->bc ? $this->bc : '000000'); + } + $commandline .= ' -border '.$width.' -bordercolor "#'.$color.'"'; + if (ereg(' \-crop ([0-9]+)x([0-9]+)\+0\+0 ', $commandline, $matches)) { + $commandline = str_replace(' -crop '.$matches[1].'x'.$matches[2].'+0+0 ', ' -crop '.($matches[1] - (2 * $width)).'x'.($matches[2] - (2 * $width)).'+0+0 ', $commandline); + } elseif (ereg(' \-'.$IMresizeParameter.' ([0-9]+)x([0-9]+) ', $commandline, $matches)) { + $commandline = str_replace(' -'.$IMresizeParameter.' '.$matches[1].'x'.$matches[2].' ', ' -'.$IMresizeParameter.' '.($matches[1] - (2 * $width)).'x'.($matches[2] - (2 * $width)).' ', $commandline); + } + unset($this->fltr[$filterkey]); + } + } + } + break; + + case 'crop': + break; + + case 'sblr': + break; + + case 'mean': + break; + + case 'smth': + break; + + case 'bvl': + break; + + case 'wmi': + break; + + case 'wmt': + break; + + case 'over': + break; + + case 'hist': + break; + + case 'fram': + break; + + case 'drop': + break; + + case 'mask': + break; + + case 'elip': + break; + + case 'ric': + break; + + } + if (!isset($this->fltr[$filterkey])) { + $this->DebugMessage('Processed $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); + } else { + $this->DebugMessage('Skipping $this->fltr['.$filterkey.'] ('.$filtercommand.') with ImageMagick', __FILE__, __LINE__); + } + } + $this->DebugMessage('Remaining $this->fltr after ImageMagick: ('.$this->phpThumbDebugVarDump($this->fltr).')', __FILE__, __LINE__); + + if (eregi('jpe?g', $outputFormat) && $this->q) { + if ($this->ImageMagickSwitchAvailable(array('quality', 'interlace'))) { + $commandline .= ' -quality '.$this->thumbnailQuality; + if ($this->config_output_interlace) { + // causes weird things with animated GIF... leave for JPEG only + $commandline .= ' -interlace line '; // Use Line or Plane to create an interlaced PNG or GIF or progressive JPEG image + } + } + } + $commandline .= ' "'.str_replace('/', DIRECTORY_SEPARATOR, $this->sourceFilename).(($outputFormat == 'gif') ? '' : '['.intval($this->sfn).']').'"'; // [0] means first frame of (GIF) animation, can be ignored + $commandline .= ' '.$outputFormat.':"'.$IMtempfilename.'"'; + if (!$this->iswindows) { + $commandline .= ' 2>&1'; + } + $this->DebugMessage('ImageMagick called as ('.$commandline.')', __FILE__, __LINE__); + $IMresult = phpthumb_functions::SafeExec($commandline); + clearstatcache(); + if (!@file_exists($IMtempfilename) || !@filesize($IMtempfilename)) { + $this->fatalerror = 'ImageMagick failed with message ('.trim($IMresult).')'; + $this->DebugMessage('ImageMagick failed with message ('.trim($IMresult).')', __FILE__, __LINE__); + if ($this->iswindows && !$IMresult) { + $this->DebugMessage('Check to make sure that PHP has read+write permissions to "'.dirname($IMtempfilename).'"', __FILE__, __LINE__); + } + + } else { + + $this->IMresizedData = file_get_contents($IMtempfilename); + $getimagesize_imresized = @GetImageSize($IMtempfilename); + if (($this->config_max_source_pixels > 0) && (($getimagesize_imresized[0] * $getimagesize_imresized[1]) > $this->config_max_source_pixels)) { + $this->DebugMessage('skipping ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() because IM output is too large ('.$getimagesize_imresized[0].'x'.$getimagesize_imresized[0].' = '.($getimagesize_imresized[0] * $getimagesize_imresized[1]).' > '.$this->config_max_source_pixels.')', __FILE__, __LINE__); + } elseif (function_exists(@$ImageCreateFunction) && ($this->gdimg_source = @$ImageCreateFunction($IMtempfilename))) { +//header('Content-Type: image/png'); +//ImageSaveAlpha($this->gdimg_source, true); +//ImagePNG($this->gdimg_source); +//exit; + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $this->DebugMessage('ImageMagickThumbnailToGD::'.$ImageCreateFunction.'() succeeded, $this->gdimg_source is now ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); + $this->DebugMessage('ImageMagickThumbnailToGD() returning $IMresizedData ('.strlen($this->IMresizedData).' bytes)', __FILE__, __LINE__); + } else { + $this->useRawIMoutput = true; + $this->DebugMessage('$this->useRawIMoutput set to TRUE because '.@$ImageCreateFunction.'('.$IMtempfilename.') failed', __FILE__, __LINE__); + } + @unlink($IMtempfilename); + return true; + + } + unlink($IMtempfilename); + + } else { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting, phpThumb_tempnam() failed', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('ImageMagickThumbnailToGD() aborting because ImageMagickCommandlineBase() failed', __FILE__, __LINE__); + } + $this->useRawIMoutput = false; + return false; + } + + + function Rotate() { + if ($this->ra || $this->ar) { + if (!function_exists('ImageRotate')) { + $this->DebugMessage('!function_exists(ImageRotate)', __FILE__, __LINE__); + return false; + } + if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); + return false; + } + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + + $rotate_angle = 0; + if ($this->ra) { + + $rotate_angle = floatval($this->ra); + + } else { + + if ($this->ar == 'x') { + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=')) { + if ($this->sourceFilename) { + if (function_exists('exif_read_data')) { + if ($exif_data = @exif_read_data($this->sourceFilename, 'IFD0')) { + // http://sylvana.net/jpegcrop/exif_orientation.html + switch (@$exif_data['Orientation']) { + case 1: + $rotate_angle = 0; + break; + case 3: + $rotate_angle = 180; + break; + case 6: + $rotate_angle = 270; + break; + case 8: + $rotate_angle = 90; + break; + + default: + $this->DebugMessage('EXIF auto-rotate failed because unknown $exif_data[Orientation] "'.@$exif_data['Orientation'].'"', __FILE__, __LINE__); + return false; + break; + } + $this->DebugMessage('EXIF auto-rotate set to '.$rotate_angle.' degrees ($exif_data[Orientation] = "'.@$exif_data['Orientation'].'")', __FILE__, __LINE__); + } else { + $this->DebugMessage('failed: exif_read_data('.$this->sourceFilename.')', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('!function_exists(exif_read_data)', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('Cannot auto-rotate from EXIF data because $this->sourceFilename is empty', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('Cannot auto-rotate from EXIF data because PHP is less than v4.2.0 ('.phpversion().')', __FILE__, __LINE__); + return false; + } + } elseif (($this->ar == 'l') && ($this->source_height > $this->source_width)) { + $rotate_angle = 270; + } elseif (($this->ar == 'L') && ($this->source_height > $this->source_width)) { + $rotate_angle = 90; + } elseif (($this->ar == 'p') && ($this->source_width > $this->source_height)) { + $rotate_angle = 90; + } elseif (($this->ar == 'P') && ($this->source_width > $this->source_height)) { + $rotate_angle = 270; + } + + } + if ($rotate_angle % 90) { + $this->is_alpha = true; + } + phpthumb_filters::ImprovedImageRotate($this->gdimg_source, $rotate_angle, $this->config_background_hexcolor, $this->bg); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + } + return true; + } + + + function FixedAspectRatio() { + // optional fixed-dimension images (regardless of aspect ratio) + + if (!$this->far) { + // do nothing + return true; + } + + if (!$this->w || !$this->h) { + return false; + } + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->is_alpha = true; + if ($this->thumbnail_image_width >= $this->thumbnail_width) { + + if ($this->w) { + $aspectratio = $this->thumbnail_image_height / $this->thumbnail_image_width; + $this->thumbnail_image_height = round($this->thumbnail_image_width * $aspectratio); + $this->thumbnail_height = ($this->h ? $this->h : $this->thumbnail_image_height); + } elseif ($this->thumbnail_image_height < $this->thumbnail_height) { + $this->thumbnail_image_height = $this->thumbnail_height; + $this->thumbnail_image_width = round($this->thumbnail_image_height / $aspectratio); + } + + } else { + if ($this->h) { + $aspectratio = $this->thumbnail_image_width / $this->thumbnail_image_height; + $this->thumbnail_image_width = round($this->thumbnail_image_height * $aspectratio); + } elseif ($this->thumbnail_image_width < $this->thumbnail_width) { + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = round($this->thumbnail_image_width / $aspectratio); + } + + } + return true; + } + + + function AntiOffsiteLinking() { + // Optional anti-offsite hijacking of the thumbnail script + $allow = true; + if ($allow && $this->config_nooffsitelink_enabled && (@$_SERVER['HTTP_REFERER'] || $this->config_nooffsitelink_require_refer)) { + $this->DebugMessage('AntiOffsiteLinking() checking $_SERVER[HTTP_REFERER] "'.@$_SERVER['HTTP_REFERER'].'"', __FILE__, __LINE__); + foreach ($this->config_nooffsitelink_valid_domains as $key => $valid_domain) { + // $_SERVER['HTTP_HOST'] contains the port number, so strip it out here to make default configuration work + list($clean_domain) = explode(':', $valid_domain); + $this->config_nooffsitelink_valid_domains[$key] = $clean_domain; + } + $parsed_url = parse_url(@$_SERVER['HTTP_REFERER']); + if (!phpthumb_functions::CaseInsensitiveInArray(@$parsed_url['host'], $this->config_nooffsitelink_valid_domains)) { + $allow = false; + $erase = $this->config_nooffsitelink_erase_image; + $message = $this->config_nooffsitelink_text_message; +$this->ErrorImage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')'); +exit; + $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is NOT in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + } else { + $this->DebugMessage('AntiOffsiteLinking() - "'.@$parsed_url['host'].'" is in $this->config_nooffsitelink_valid_domains ('.implode(';', $this->config_nooffsitelink_valid_domains).')', __FILE__, __LINE__); + } + } + + if ($allow && $this->config_nohotlink_enabled && eregi('^(f|ht)tps?\://', $this->src)) { + $parsed_url = parse_url($this->src); + if (!phpthumb_functions::CaseInsensitiveInArray(@$parsed_url['host'], $this->config_nohotlink_valid_domains)) { + // This domain is not allowed + $allow = false; + $erase = $this->config_nohotlink_erase_image; + $message = $this->config_nohotlink_text_message; + $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is NOT in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); + } else { + $this->DebugMessage('AntiOffsiteLinking() - "'.$parsed_url['host'].'" is in $this->config_nohotlink_valid_domains ('.implode(';', $this->config_nohotlink_valid_domains).')', __FILE__, __LINE__); + } + } + + if ($allow) { + $this->DebugMessage('AntiOffsiteLinking() says this is allowed', __FILE__, __LINE__); + return true; + } + + if (!phpthumb_functions::IsHexColor($this->config_error_bgcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_error_bgcolor.'" for $this->config_error_bgcolor'); + } + if (!phpthumb_functions::IsHexColor($this->config_error_textcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_error_textcolor.'" for $this->config_error_textcolor'); + } + if ($erase) { + + return $this->ErrorImage($message, $this->thumbnail_width, $this->thumbnail_height, $this->config_error_bgcolor, $this->config_error_textcolor, $this->config_error_fontsize); + + } else { + + $this->config_nooffsitelink_watermark_src = $this->ResolveFilenameToAbsolute($this->config_nooffsitelink_watermark_src); + if (is_file($this->config_nooffsitelink_watermark_src)) { + + if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying watermark', __FILE__, __LINE__); + return false; + } + $watermark_img = $this->ImageCreateFromStringReplacement(file_get_contents($this->config_nooffsitelink_watermark_src)); + $phpthumbFilters = new phpthumb_filters(); + $phpthumbFilters->phpThumbObject = $this; + $opacity = 50; + $margin = 5; + $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $watermark_img, '*', $opacity, $margin); + ImageDestroy($watermark_img); + unset($phpthumbFilters); + + } else { + + $nohotlink_text_array = explode("\n", wordwrap($message, floor($this->thumbnail_width / ImageFontWidth($this->config_error_fontsize)), "\n")); + $nohotlink_text_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_error_textcolor); + + $topoffset = round(($this->thumbnail_height - (count($nohotlink_text_array) * ImageFontHeight($this->config_error_fontsize))) / 2); + + $rowcounter = 0; + $this->DebugMessage('AntiOffsiteLinking() writing '.count($nohotlink_text_array).' lines of text "'.$message.'" (in #'.$this->config_error_textcolor.') on top of image', __FILE__, __LINE__); + foreach ($nohotlink_text_array as $textline) { + $leftoffset = max(0, round(($this->thumbnail_width - (strlen($textline) * ImageFontWidth($this->config_error_fontsize))) / 2)); + ImageString($this->gdimg_output, $this->config_error_fontsize, $leftoffset, $topoffset + ($rowcounter++ * ImageFontHeight($this->config_error_fontsize)), $textline, $nohotlink_text_color); + } + + } + + } + return true; + } + + + function AlphaChannelFlatten() { + if (!$this->is_alpha) { + // image doesn't have alpha transparency, no need to flatten + $this->DebugMessage('skipping AlphaChannelFlatten() because !$this->is_alpha', __FILE__, __LINE__); + return false; + } + switch ($this->thumbnailFormat) { + case 'png': + case 'ico': + // image has alpha transparency, but output as PNG or ICO which can handle it + $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'")', __FILE__, __LINE__); + return false; + break; + + case 'gif': + // image has alpha transparency, but output as GIF which can handle only single-color transparency + $CurrentImageColorTransparent = ImageColorTransparent($this->gdimg_output); + if ($CurrentImageColorTransparent == -1) { + // no transparent color defined + + if (phpthumb_functions::gd_version() < 2.0) { + $this->DebugMessage('AlphaChannelFlatten() failed because GD version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + + if ($img_alpha_mixdown_dither = @ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { + + for ($i = 0; $i <= 255; $i++) { + $dither_color[$i] = ImageColorAllocate($img_alpha_mixdown_dither, $i, $i, $i); + } + + // scan through current truecolor image copy alpha channel to temp image as grayscale + for ($x = 0; $x < $this->thumbnail_width; $x++) { + for ($y = 0; $y < $this->thumbnail_height; $y++) { + $PixelColor = phpthumb_functions::GetPixelColor($this->gdimg_output, $x, $y); + ImageSetPixel($img_alpha_mixdown_dither, $x, $y, $dither_color[($PixelColor['alpha'] * 2)]); + } + } + + // dither alpha channel grayscale version down to 2 colors + ImageTrueColorToPalette($img_alpha_mixdown_dither, true, 2); + + // reduce color palette to 256-1 colors (leave one palette position for transparent color) + ImageTrueColorToPalette($this->gdimg_output, true, 255); + + // allocate a new color for transparent color index + $TransparentColor = ImageColorAllocate($this->gdimg_output, 1, 254, 253); + ImageColorTransparent($this->gdimg_output, $TransparentColor); + + // scan through alpha channel image and note pixels with >50% transparency + $TransparentPixels = array(); + for ($x = 0; $x < $this->thumbnail_width; $x++) { + for ($y = 0; $y < $this->thumbnail_height; $y++) { + $AlphaChannelPixel = phpthumb_functions::GetPixelColor($img_alpha_mixdown_dither, $x, $y); + if ($AlphaChannelPixel['red'] > 127) { + ImageSetPixel($this->gdimg_output, $x, $y, $TransparentColor); + } + } + } + ImageDestroy($img_alpha_mixdown_dither); + + $this->DebugMessage('AlphaChannelFlatten() set image to 255+1 colors with transparency for GIF output', __FILE__, __LINE__); + return true; + + } else { + $this->DebugMessage('AlphaChannelFlatten() failed ImageCreate('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); + return false; + } + + } else { + // a single transparent color already defined, leave as-is + $this->DebugMessage('skipping AlphaChannelFlatten() because ($this->thumbnailFormat == "'.$this->thumbnailFormat.'") and ImageColorTransparent returned "'.$CurrentImageColorTransparent.'"', __FILE__, __LINE__); + return true; + } + break; + } + $this->DebugMessage('continuing AlphaChannelFlatten() for output format "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); + // image has alpha transparency, and is being output in a format that doesn't support it -- flatten + if ($gdimg_flatten_temp = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height)) { + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); + ImageFilledRectangle($gdimg_flatten_temp, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); + ImageCopy($gdimg_flatten_temp, $this->gdimg_output, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); + + ImageAlphaBlending($this->gdimg_output, true); + ImageSaveAlpha($this->gdimg_output, false); + ImageColorTransparent($this->gdimg_output, -1); + ImageCopy($this->gdimg_output, $gdimg_flatten_temp, 0, 0, 0, 0, $this->thumbnail_width, $this->thumbnail_height); + + ImageDestroy($gdimg_flatten_temp); + return true; + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + return false; + } + + + function ApplyFilters() { + if ($this->fltr && is_array($this->fltr)) { + if (!include_once(dirname(__FILE__).'/phpthumb.filters.php')) { + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.filters.php" which is required for applying filters ('.implode(';', $this->fltr).')', __FILE__, __LINE__); + return false; + } + $phpthumbFilters = new phpthumb_filters(); + $phpthumbFilters->phpThumbObject = $this; + foreach ($this->fltr as $filtercommand) { + @list($command, $parameter) = explode('|', $filtercommand, 2); + $this->DebugMessage('Attempting to process filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__); + switch ($command) { + case 'brit': // Brightness + $phpthumbFilters->Brightness($this->gdimg_output, $parameter); + break; + + case 'cont': // Contrast + $phpthumbFilters->Contrast($this->gdimg_output, $parameter); + break; + + case 'ds': // Desaturation + $phpthumbFilters->Desaturate($this->gdimg_output, $parameter, ''); + break; + + case 'sat': // Saturation + $phpthumbFilters->Saturation($this->gdimg_output, $parameter, ''); + break; + + case 'gray': // Grayscale + $phpthumbFilters->Grayscale($this->gdimg_output); + break; + + case 'clr': // Colorize + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Colorize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($amount, $color) = explode('|', $parameter); + $phpthumbFilters->Colorize($this->gdimg_output, $amount, $color); + break; + + case 'sep': // Sepia + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Sepia() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($amount, $color) = explode('|', $parameter); + $phpthumbFilters->Sepia($this->gdimg_output, $amount, $color); + break; + + case 'gam': // Gamma correction + $phpthumbFilters->Gamma($this->gdimg_output, $parameter); + break; + + case 'neg': // Negative colors + $phpthumbFilters->Negative($this->gdimg_output); + break; + + case 'th': // Threshold + $phpthumbFilters->Threshold($this->gdimg_output, $parameter); + break; + + case 'rcd': // ReduceColorDepth + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping ReduceColorDepth() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($colors, $dither) = explode('|', $parameter); + $colors = ($colors ? (int) $colors : 256); + $dither = ((strlen($dither) > 0) ? (bool) $dither : true); + $phpthumbFilters->ReduceColorDepth($this->gdimg_output, $colors, $dither); + break; + + case 'flip': // Flip + $phpthumbFilters->Flip($this->gdimg_output, (strpos(strtolower($parameter), 'x') !== false), (strpos(strtolower($parameter), 'y') !== false)); + break; + + case 'edge': // EdgeDetect + $phpthumbFilters->EdgeDetect($this->gdimg_output); + break; + + case 'emb': // Emboss + $phpthumbFilters->Emboss($this->gdimg_output); + break; + + case 'bvl': // Bevel + @list($width, $color1, $color2) = explode('|', $parameter); + $phpthumbFilters->Bevel($this->gdimg_output, $width, $color1, $color2); + break; + + case 'lvl': // autoLevels + @list($band, $method, $threshold) = explode('|', $parameter); + $band = ($band ? ereg_replace('[^RGBA\\*]', '', strtoupper($band)) : '*'); + $method = ((strlen($method) > 0) ? intval($method) : 2); + $threshold = ((strlen($threshold) > 0) ? floatval($threshold) : 0.1); + + $phpthumbFilters->HistogramStretch($this->gdimg_output, $band, $method, $threshold); + break; + + case 'wb': // WhiteBalance + $phpthumbFilters->WhiteBalance($this->gdimg_output, $parameter); + break; + + case 'hist': // Histogram overlay + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping HistogramOverlay() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + break; + } + @list($bands, $colors, $width, $height, $alignment, $opacity, $margin_x, $margin_y) = explode('|', $parameter); + $bands = ($bands ? $bands : '*'); + $colors = ($colors ? $colors : ''); + $width = ($width ? $width : 0.25); + $height = ($height ? $height : 0.25); + $alignment = ($alignment ? $alignment : 'BR'); + $opacity = ($opacity ? $opacity : 50); + $margin_x = ($margin_x ? $margin_x : 5); + $margin_y = $margin_y; // just to note it wasn't forgotten, but let the value always pass unchanged + $phpthumbFilters->HistogramOverlay($this->gdimg_output, $bands, $colors, $width, $height, $alignment, $opacity, $margin_x, $margin_y); + break; + + case 'fram': // Frame + @list($frame_width, $edge_width, $color_frame, $color1, $color2) = explode('|', $parameter); + $phpthumbFilters->Frame($this->gdimg_output, $frame_width, $edge_width, $color_frame, $color1, $color2); + break; + + case 'drop': // DropShadow + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping DropShadow() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $this->is_alpha = true; + @list($distance, $width, $color, $angle, $fade) = explode('|', $parameter); + $phpthumbFilters->DropShadow($this->gdimg_output, $distance, $width, $color, $angle, $fade); + break; + + case 'mask': // Mask cropping + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Mask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $mask_filename = $this->ResolveFilenameToAbsolute($parameter); + if (@is_readable($mask_filename) && ($fp_mask = @fopen($mask_filename, 'rb'))) { + $MaskImageData = ''; + do { + $buffer = fread($fp_mask, 8192); + $MaskImageData .= $buffer; + } while (strlen($buffer) > 0); + fclose($fp_mask); + if ($gdimg_mask = $this->ImageCreateFromStringReplacement($MaskImageData)) { + $this->is_alpha = true; + $phpthumbFilters->ApplyMask($gdimg_mask, $this->gdimg_output); + ImageDestroy($gdimg_mask); + } else { + $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$mask_filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('Cannot open mask file "'.$mask_filename.'"', __FILE__, __LINE__); + } + break; + + case 'elip': // Elipse cropping + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Elipse() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $this->is_alpha = true; + $phpthumbFilters->Elipse($this->gdimg_output); + break; + + case 'ric': // RoundedImageCorners + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping RoundedImageCorners() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + @list($radius_x, $radius_y) = explode('|', $parameter); + if (($radius_x < 1) || ($radius_y < 1)) { + $this->DebugMessage('Skipping RoundedImageCorners('.$radius_x.', '.$radius_y.') because x/y radius is less than 1', __FILE__, __LINE__); + break; + } + $this->is_alpha = true; + $phpthumbFilters->RoundedImageCorners($this->gdimg_output, $radius_x, $radius_y); + break; + + case 'crop': // Crop + @list($left, $right, $top, $bottom) = explode('|', $parameter); + $phpthumbFilters->Crop($this->gdimg_output, $left, $right, $top, $bottom); + break; + + case 'bord': // Border + @list($border_width, $radius_x, $radius_y, $hexcolor_border) = explode('|', $parameter); + $this->is_alpha = true; + $phpthumbFilters->ImageBorder($this->gdimg_output, $border_width, $radius_x, $radius_y, $hexcolor_border); + break; + + case 'over': // Overlay + @list($filename, $underlay, $margin, $opacity) = explode('|', $parameter); + $underlay = (bool) ($underlay ? $underlay : false); + $margin = ((strlen($margin) > 0) ? $margin : ($underlay ? 0.1 : 0.0)); + $opacity = ((strlen($opacity) > 0) ? $opacity : 100); + if (($margin > 0) && ($margin < 1)) { + $margin = min(0.499, $margin); + } elseif (($margin > -1) && ($margin < 0)) { + $margin = max(-0.499, $margin); + } + + $filename = $this->ResolveFilenameToAbsolute($filename); + if (@is_readable($filename) && ($fp_watermark = @fopen($filename, 'rb'))) { + $WatermarkImageData = ''; + do { + $buffer = fread($fp_watermark, 8192); + $WatermarkImageData .= $buffer; + } while (strlen($buffer) > 0); + fclose($fp_watermark); + if ($img_watermark = $this->ImageCreateFromStringReplacement($WatermarkImageData)) { + if ($margin < 1) { + $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * (ImageSX($this->gdimg_output) * $margin))); + $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * (ImageSY($this->gdimg_output) * $margin))); + } else { + $resized_x = max(1, ImageSX($this->gdimg_output) - round(2 * $margin)); + $resized_y = max(1, ImageSY($this->gdimg_output) - round(2 * $margin)); + } + + if ($underlay) { + + if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output))) { + ImageAlphaBlending($img_watermark_resized, false); + ImageSaveAlpha($img_watermark_resized, true); + $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); + if ($img_source_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { + ImageAlphaBlending($img_source_resized, false); + ImageSaveAlpha($img_source_resized, true); + $this->ImageResizeFunction($img_source_resized, $this->gdimg_output, 0, 0, 0, 0, ImageSX($img_source_resized), ImageSY($img_source_resized), ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + $phpthumbFilters->WatermarkOverlay($img_watermark_resized, $img_source_resized, 'C', $opacity, $margin); + ImageCopy($this->gdimg_output, $img_watermark_resized, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); + } + ImageDestroy($img_watermark_resized); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.ImageSX($this->gdimg_output).', '.ImageSY($this->gdimg_output).')', __FILE__, __LINE__); + } + + } else { // overlay + + if ($img_watermark_resized = phpthumb_functions::ImageCreateFunction($resized_x, $resized_y)) { + ImageAlphaBlending($img_watermark_resized, false); + ImageSaveAlpha($img_watermark_resized, true); + $this->ImageResizeFunction($img_watermark_resized, $img_watermark, 0, 0, 0, 0, ImageSX($img_watermark_resized), ImageSY($img_watermark_resized), ImageSX($img_watermark), ImageSY($img_watermark)); + $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark_resized, 'C', $opacity, $margin); + ImageDestroy($img_watermark_resized); + } else { + $this->DebugMessage('phpthumb_functions::ImageCreateFunction('.$resized_x.', '.$resized_y.')', __FILE__, __LINE__); + } + + } + ImageDestroy($img_watermark); + + } else { + $this->DebugMessage('ImageCreateFromStringReplacement() failed for "'.$filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('Cannot open overlay file "'.$filename.'"', __FILE__, __LINE__); + } + break; + + case 'wmi': // WaterMarkImage + @list($filename, $alignment, $opacity, $margin['x'], $margin['y']) = explode('|', $parameter); + $alignment = ($alignment ? $alignment : 'BR'); + $opacity = (strlen($opacity) ? $opacity : 50); + $margins = array('x', 'y'); + foreach ($margins as $xy) { + $margin[$xy] = (strlen($margin[$xy]) ? $margin[$xy] : 5); + if (($margin[$xy] > 0) && ($margin[$xy] < 1)) { + $margin[$xy] = min(0.499, $margin[$xy]); + } elseif (($margin[$xy] > -1) && ($margin[$xy] < 0)) { + $margin[$xy] = max(-0.499, $margin[$xy]); + } + } + + $filename = $this->ResolveFilenameToAbsolute($filename); + if (@is_readable($filename)) { + if ($img_watermark = $this->ImageCreateFromFilename($filename)) { + // great + $phpthumbFilters->WatermarkOverlay($this->gdimg_output, $img_watermark, $alignment, $opacity, $margin['x'], $margin['y']); + ImageDestroy($img_watermark); + } else { + $this->DebugMessage('ImageCreateFromFilename() failed for "'.$filename.'"', __FILE__, __LINE__); + } + } else { + $this->DebugMessage('!is_readable('.$filename.')', __FILE__, __LINE__); + } + break; + + case 'wmt': // WaterMarkText + @list($text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend) = explode('|', $parameter); + $text = ($text ? iconv("EUC-KR","UTF-8",$text) : ''); + $size = ($size ? $size : 3); + $alignment = ($alignment ? $alignment : 'BR'); + $hex_color = ($hex_color ? $hex_color : '000000'); + $ttffont = ($ttffont ? $ttffont : ''); + $opacity = (strlen($opacity) ? $opacity : 50); + $margin = (strlen($margin) ? $margin : 5); + $angle = (strlen($angle) ? $angle : 0); + $bg_color = ($bg_color ? $bg_color : false); + $bg_opacity = ($bg_opacity ? $bg_opacity : 0); + $fillextend = ($fillextend ? $fillextend : ''); + + if (basename($ttffont) == $ttffont) { + $ttffont = realpath($this->config_ttf_directory.DIRECTORY_SEPARATOR.$ttffont); + } else { + $ttffont = $this->ResolveFilenameToAbsolute($ttffont); + } + $phpthumbFilters->WatermarkText($this->gdimg_output, $text, $size, $alignment, $hex_color, $ttffont, $opacity, $margin, $angle, $bg_color, $bg_opacity, $fillextend); + break; + + case 'blur': // Blur + @list($radius) = explode('|', $parameter); + $radius = ($radius ? $radius : 1); + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping Blur() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + $phpthumbFilters->Blur($this->gdimg_output, $radius); + break; + + case 'gblr': // Gaussian Blur + $phpthumbFilters->BlurGaussian($this->gdimg_output); + break; + + case 'sblr': // Selective Blur + $phpthumbFilters->BlurSelective($this->gdimg_output); + break; + + case 'mean': // MeanRemoval blur + $phpthumbFilters->MeanRemoval($this->gdimg_output); + break; + + case 'smth': // Smooth blur + $phpthumbFilters->Smooth($this->gdimg_output, $parameter); + break; + + case 'usm': // UnSharpMask sharpening + @list($amount, $radius, $threshold) = explode('|', $parameter); + $amount = ($amount ? $amount : 80); + $radius = ($radius ? $radius : 0.5); + $threshold = (strlen($threshold) ? $threshold : 3); + if (phpthumb_functions::gd_version() >= 2.0) { + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.unsharp.php')) { + $include_error = ob_get_contents(); + if ($include_error) { + $this->DebugMessage('include_once("'.dirname(__FILE__).'/phpthumb.unsharp.php") generated message: "'.$include_error.'"', __FILE__, __LINE__); + } + $this->DebugMessage('Error including "'.dirname(__FILE__).'/phpthumb.unsharp.php" which is required for unsharp masking', __FILE__, __LINE__); + ob_end_clean(); + return false; + } + ob_end_clean(); + phpUnsharpMask::applyUnsharpMask($this->gdimg_output, $amount, $radius, $threshold); + } else { + $this->DebugMessage('Skipping unsharp mask because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + break; + + case 'rot': // ROTate + @list($angle, $bgcolor) = explode('|', $parameter); + $phpthumbFilters->ImprovedImageRotate($this->gdimg_output, $angle, $bgcolor); + break; + } + $this->DebugMessage('Finished processing filter command "'.$command.'('.$parameter.')"', __FILE__, __LINE__); + } + } + return true; + } + + + function MaxFileSize() { + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping MaxFileSize() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + if ($this->maxb > 0) { + switch ($this->thumbnailFormat) { + case 'png': + case 'gif': + $imgRenderFunction = 'image'.$this->thumbnailFormat; + + ob_start(); + $imgRenderFunction($this->gdimg_output); + $imgdata = ob_get_contents(); + ob_end_clean(); + + if (strlen($imgdata) > $this->maxb) { + for ($i = 8; $i >= 1; $i--) { + $tempIMG = ImageCreateTrueColor(ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + ImageCopy($tempIMG, $this->gdimg_output, 0, 0, 0, 0, ImageSX($this->gdimg_output), ImageSY($this->gdimg_output)); + ImageTrueColorToPalette($tempIMG, true, pow(2, $i)); + ob_start(); + $imgRenderFunction($tempIMG); + $imgdata = ob_get_contents(); + ob_end_clean(); + + if (strlen($imgdata) <= $this->maxb) { + ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); + break; + } + } + } + if (strlen($imgdata) > $this->maxb) { + ImageTrueColorToPalette($this->gdimg_output, true, pow(2, $i)); + return false; + } + break; + + case 'jpeg': + ob_start(); + ImageJPEG($this->gdimg_output); + $imgdata = ob_get_contents(); + ob_end_clean(); + + $OriginalJPEGquality = $this->thumbnailQuality; + if (strlen($imgdata) > $this->maxb) { + for ($i = 3; $i < 20; $i++) { + $q = round(100 * (1 - log10($i / 2))); + ob_start(); + ImageJPEG($this->gdimg_output, '', $q); + $imgdata = ob_get_contents(); + ob_end_clean(); + + $this->thumbnailQuality = $q; + if (strlen($imgdata) <= $this->maxb) { + break; + } + } + } + if (strlen($imgdata) > $this->maxb) { + return false; + } + break; + + default: + return false; + break; + } + } + return true; + } + + + function CalculateThumbnailDimensions() { +//echo $this->source_width.'x'.$this->source_height.'
    '; + $this->thumbnailCropX = ($this->sx ? (($this->sx >= 1) ? $this->sx : round($this->sx * $this->source_width)) : 0); +//echo $this->thumbnailCropX.'
    '; + $this->thumbnailCropY = ($this->sy ? (($this->sy >= 1) ? $this->sy : round($this->sy * $this->source_height)) : 0); +//echo $this->thumbnailCropY.'
    '; + $this->thumbnailCropW = ($this->sw ? (($this->sw >= 1) ? $this->sw : round($this->sw * $this->source_width)) : $this->source_width); +//echo $this->thumbnailCropW.'
    '; + $this->thumbnailCropH = ($this->sh ? (($this->sh >= 1) ? $this->sh : round($this->sh * $this->source_height)) : $this->source_height); +//echo $this->thumbnailCropH.'
    '; + + // limit source area to original image area + $this->thumbnailCropW = max(1, min($this->thumbnailCropW, $this->source_width - $this->thumbnailCropX)); + $this->thumbnailCropH = max(1, min($this->thumbnailCropH, $this->source_height - $this->thumbnailCropY)); + + $this->DebugMessage('CalculateThumbnailDimensions() [x,y,w,h] initially set to ['.$this->thumbnailCropX.','.$this->thumbnailCropY.','.$this->thumbnailCropW.','.$this->thumbnailCropH.']', __FILE__, __LINE__); + + + if ($this->zc && $this->w && $this->h) { + // Zoom Crop + // retain proportional resizing we did above, but crop off larger dimension so smaller + // dimension fully fits available space + + $scaling_X = $this->source_width / $this->w; + $scaling_Y = $this->source_height / $this->h; + if ($scaling_X > $scaling_Y) { + // some of the width will need to be cropped + $allowable_width = $this->source_width / $scaling_X * $scaling_Y; + $this->thumbnailCropW = round($allowable_width); + $this->thumbnailCropX = round(($this->source_width - $allowable_width) / 2); + + } elseif ($scaling_Y > $scaling_X) { + // some of the height will need to be cropped + $allowable_height = $this->source_height / $scaling_Y * $scaling_X; + $this->thumbnailCropH = round($allowable_height); + $this->thumbnailCropY = round(($this->source_height - $allowable_height) / 2); + + } else { + // image fits perfectly, no cropping needed + } + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = $this->thumbnail_height; + + } elseif ($this->iar && $this->w && $this->h) { + + // Ignore Aspect Ratio + // stretch image to fit exactly 'w' x 'h' + $this->thumbnail_width = $this->w; + $this->thumbnail_height = $this->h; + $this->thumbnail_image_width = $this->thumbnail_width; + $this->thumbnail_image_height = $this->thumbnail_height; + + } else { + + $original_aspect_ratio = $this->thumbnailCropW / $this->thumbnailCropH; + if ($this->aoe) { + if ($this->w && $this->h) { + $maxwidth = min($this->w, $this->h * $original_aspect_ratio); + $maxheight = min($this->h, $this->w / $original_aspect_ratio); + } elseif ($this->w) { + $maxwidth = $this->w; + $maxheight = $this->w / $original_aspect_ratio; + } elseif ($this->h) { + $maxwidth = $this->h * $original_aspect_ratio; + $maxheight = $this->h; + } else { + $maxwidth = $this->thumbnailCropW; + $maxheight = $this->thumbnailCropH; + } + } else { + $maxwidth = phpthumb_functions::nonempty_min($this->w, $this->thumbnailCropW, $this->config_output_maxwidth); + $maxheight = phpthumb_functions::nonempty_min($this->h, $this->thumbnailCropH, $this->config_output_maxheight); +//echo $maxwidth.'x'.$maxheight.'
    '; + $maxwidth = min($maxwidth, $maxheight * $original_aspect_ratio); + $maxheight = min($maxheight, $maxwidth / $original_aspect_ratio); +//echo $maxwidth.'x'.$maxheight.'
    '; + } + + $this->thumbnail_image_width = $maxwidth; + $this->thumbnail_image_height = $maxheight; + $this->thumbnail_width = $maxwidth; + $this->thumbnail_height = $maxheight; + + $this->FixedAspectRatio(); + } + + $this->thumbnail_width = max(1, floor($this->thumbnail_width)); + $this->thumbnail_height = max(1, floor($this->thumbnail_height)); + return true; + } + + + function CreateGDoutput() { + $this->CalculateThumbnailDimensions(); + + // Create the GD image (either true-color or 256-color, depending on GD version) + $this->gdimg_output = phpthumb_functions::ImageCreateFunction($this->thumbnail_width, $this->thumbnail_height); + + // Images that have transparency must have the background filled with the configured 'bg' color + // otherwise the transparent color will appear as black + ImageSaveAlpha($this->gdimg_output, true); + if ($this->is_alpha && phpthumb_functions::gd_version() >= 2) { + + ImageAlphaBlending($this->gdimg_output, false); + $output_full_alpha = phpthumb_functions::ImageColorAllocateAlphaSafe($this->gdimg_output, 255, 255, 255, 127); + ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $output_full_alpha); + + } else { + + $current_transparent_color = ImageColorTransparent($this->gdimg_source); + if ($this->bg || (@$current_transparent_color >= 0)) { + + $this->config_background_hexcolor = ($this->bg ? $this->bg : $this->config_background_hexcolor); + if (!phpthumb_functions::IsHexColor($this->config_background_hexcolor)) { + return $this->ErrorImage('Invalid hex color string "'.$this->config_background_hexcolor.'" for parameter "bg"'); + } + $background_color = phpthumb_functions::ImageHexColorAllocate($this->gdimg_output, $this->config_background_hexcolor); + ImageFilledRectangle($this->gdimg_output, 0, 0, $this->thumbnail_width, $this->thumbnail_height, $background_color); + + } + + } + $this->DebugMessage('CreateGDoutput() returning canvas "'.$this->thumbnail_width.'x'.$this->thumbnail_height.'"', __FILE__, __LINE__); + return true; + } + + function SetOrientationDependantWidthHeight() { + $this->DebugMessage('SetOrientationDependantWidthHeight() starting with "'.$this->source_width.'"x"'.$this->source_height.'"', __FILE__, __LINE__); + if ($this->source_height > $this->source_width) { + // portrait + $this->w = phpthumb_functions::OneOfThese($this->wp, $this->w, $this->ws, $this->wl); + $this->h = phpthumb_functions::OneOfThese($this->hp, $this->h, $this->hs, $this->hl); + } elseif ($this->source_height < $this->source_width) { + // landscape + $this->w = phpthumb_functions::OneOfThese($this->wl, $this->w, $this->ws, $this->wp); + $this->h = phpthumb_functions::OneOfThese($this->hl, $this->h, $this->hs, $this->hp); + } else { + // square + $this->w = phpthumb_functions::OneOfThese($this->ws, $this->w, $this->wl, $this->wp); + $this->h = phpthumb_functions::OneOfThese($this->hs, $this->h, $this->hl, $this->hp); + } + //$this->w = round($this->w ? $this->w : (($this->h && $this->source_height) ? $this->h * $this->source_width / $this->source_height : $this->w)); + //$this->h = round($this->h ? $this->h : (($this->w && $this->source_width) ? $this->w * $this->source_height / $this->source_width : $this->h)); + $this->DebugMessage('SetOrientationDependantWidthHeight() setting w="'.intval($this->w).'", h="'.intval($this->h).'"', __FILE__, __LINE__); + return true; + } + + function ExtractEXIFgetImageSize() { + $this->DebugMessage('starting ExtractEXIFgetImageSize()', __FILE__, __LINE__); + + if (is_resource($this->gdimg_source)) { + + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + + $this->SetOrientationDependantWidthHeight(); + + } elseif ($this->rawImageData && !$this->sourceFilename) { + + $this->DebugMessage('bypassing EXIF and GetImageSize sections because $this->rawImageData is set and $this->sourceFilename is not set', __FILE__, __LINE__); + + } + + if (is_null($this->getimagesizeinfo)) { + $this->getimagesizeinfo = @GetImageSize($this->sourceFilename); + } + + if (!empty($this->getimagesizeinfo)) { + // great + $this->getimagesizeinfo['filesize'] = @filesize($this->sourceFilename); + } elseif (!$this->rawImageData) { + $this->DebugMessage('GetImageSize("'.$this->sourceFilename.'") failed', __FILE__, __LINE__); + } + + if ($this->config_prefer_imagemagick) { + if ($this->ImageMagickThumbnailToGD()) { + return true; + } + $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); + } + + $this->source_width = $this->getimagesizeinfo[0]; + $this->source_height = $this->getimagesizeinfo[1]; + + $this->SetOrientationDependantWidthHeight(); + + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.2.0', '>=') && function_exists('exif_read_data')) { + $this->exif_raw_data = @exif_read_data($this->sourceFilename, 0, true); + } + if (function_exists('exif_thumbnail') && ($this->getimagesizeinfo[2] == 2)) { + // Extract EXIF info from JPEGs + + $this->exif_thumbnail_width = ''; + $this->exif_thumbnail_height = ''; + $this->exif_thumbnail_type = ''; + + // The parameters width, height and imagetype are available since PHP v4.3.0 + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) { + + $this->exif_thumbnail_data = @exif_thumbnail($this->sourceFilename, $this->exif_thumbnail_width, $this->exif_thumbnail_height, $this->exif_thumbnail_type); + + } else { + + // older versions of exif_thumbnail output an error message but NOT return false on failure + ob_start(); + $this->exif_thumbnail_data = exif_thumbnail($this->sourceFilename); + $exit_thumbnail_error = ob_get_contents(); + ob_end_clean(); + if (!$exit_thumbnail_error && $this->exif_thumbnail_data) { + + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + $this->exif_thumbnail_width = ImageSX($gdimg_exif_temp); + $this->exif_thumbnail_height = ImageSY($gdimg_exif_temp); + $this->exif_thumbnail_type = 2; // (2 == JPEG) before PHP v4.3.0 only JPEG format EXIF thumbnails are returned + unset($gdimg_exif_temp); + } else { + return $this->ErrorImage('Failed - $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data) in '.__FILE__.' on line '.__LINE__); + } + + } + + } + + } elseif (!function_exists('exif_thumbnail')) { + + $this->DebugMessage('exif_thumbnail() does not exist, cannot extract EXIF thumbnail', __FILE__, __LINE__); + return false; + + } + + $this->DebugMessage('EXIF thumbnail extraction: (size='.strlen($this->exif_thumbnail_data).'; type="'.$this->exif_thumbnail_type.'"; '.intval($this->exif_thumbnail_width).'x'.intval($this->exif_thumbnail_height).')', __FILE__, __LINE__); + + // see if EXIF thumbnail can be used directly with no processing + if ($this->config_use_exif_thumbnail_for_speed && $this->exif_thumbnail_data) { + while (true) { + if (!$this->xto) { + $source_ar = $this->source_width / $this->source_height; + $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; + if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { + $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); + break; + } + if ($this->w && ($this->w != $this->exif_thumbnail_width)) { + $this->DebugMessage('not using EXIF thumbnail because $this->w != $this->exif_thumbnail_width ('.$this->w.' != '.$this->exif_thumbnail_width.')', __FILE__, __LINE__); + break; + } + if ($this->h && ($this->h != $this->exif_thumbnail_height)) { + $this->DebugMessage('not using EXIF thumbnail because $this->h != $this->exif_thumbnail_height ('.$this->h.' != '.$this->exif_thumbnail_height.')', __FILE__, __LINE__); + break; + } + $CannotBeSetParameters = array('sx', 'sy', 'sh', 'sw', 'far', 'bg', 'bc', 'fltr', 'phpThumbDebug'); + foreach ($CannotBeSetParameters as $parameter) { + if ($this->$parameter) { + break 2; + } + } + } + + $this->DebugMessage('setting $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data)', __FILE__, __LINE__); + $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data); + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + return true; + } + } + + if (($this->config_max_source_pixels > 0) && (($this->source_width * $this->source_height) > $this->config_max_source_pixels)) { + + // Source image is larger than would fit in available PHP memory. + // If ImageMagick is installed, use it to generate the thumbnail. + // Else, if an EXIF thumbnail is available, use that as the source image. + // Otherwise, no choice but to fail with an error message + $this->DebugMessage('image is '.$this->source_width.'x'.$this->source_height.' and therefore contains more pixels ('.($this->source_width * $this->source_height).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); + if (!$this->config_prefer_imagemagick && $this->ImageMagickThumbnailToGD()) { + // excellent, we have a thumbnailed source image + return true; + } + + } + return true; + } + + + function SetCacheFilename() { + if (!is_null($this->cache_filename)) { + $this->DebugMessage('$this->cache_filename already set, skipping SetCacheFilename()', __FILE__, __LINE__); + return true; + } + $this->setOutputFormat(); + $this->setCacheDirectory(); + if (!$this->config_cache_directory) { + $this->DebugMessage('SetCacheFilename() failed because $this->config_cache_directory is empty', __FILE__, __LINE__); + return false; + } + + if (!$this->sourceFilename && !$this->rawImageData && $this->src) { + $this->sourceFilename = $this->ResolveFilenameToAbsolute($this->src); + } + + if ($this->config_cache_default_only_suffix && $this->sourceFilename) { + // simplified cache filenames: + // only use default parameters in phpThumb.config.php + // substitute source filename into * in $this->config_cache_default_only_suffix + // (eg: '*_thumb' becomes 'picture_thumb.jpg') + if (strpos($this->config_cache_default_only_suffix, '*') === false) { + $this->DebugMessage('aborting simplified caching filename because no * in "'.$this->config_cache_default_only_suffix.'"', __FILE__, __LINE__); + } else { + eregi('(.+)(\.[a-z0-9]+)?$', basename($this->sourceFilename), $matches); + $this->cache_filename = $this->config_cache_directory.DIRECTORY_SEPARATOR.rawurlencode(str_replace('*', @$matches[1], $this->config_cache_default_only_suffix)).'.'.strtolower($this->thumbnailFormat); + return true; + } + } + + $this->cache_filename = ''; + $broad_directory_name = ''; + if ($this->new) { + $broad_directory_name = strtolower(md5($this->new)); + $this->cache_filename .= '_new'.$broad_directory_name; + } elseif ($this->md5s) { + // source image MD5 hash provided + $this->DebugMessage('SetCacheFilename() _raw set from $this->md5s = "'.$this->md5s.'"', __FILE__, __LINE__); + $broad_directory_name = $this->md5s; + $this->cache_filename .= '_raw'.$this->md5s; + } elseif (!$this->src && $this->rawImageData) { + $this->DebugMessage('SetCacheFilename() _raw set from md5($this->rawImageData) = "'.md5($this->rawImageData).'"', __FILE__, __LINE__); + $broad_directory_name = strtolower(md5($this->rawImageData)); + $this->cache_filename .= '_raw'.$broad_directory_name; + } else { + $this->DebugMessage('SetCacheFilename() _src set from md5($this->sourceFilename) "'.$this->sourceFilename.'" = "'.md5($this->sourceFilename).'"', __FILE__, __LINE__); + $broad_directory_name = strtolower(md5($this->sourceFilename)); + $this->cache_filename .= '_src'.$broad_directory_name; + } + if (@$_SERVER['HTTP_REFERER'] && $this->config_nooffsitelink_enabled) { + $parsed_url1 = @parse_url(@$_SERVER['HTTP_REFERER']); + $parsed_url2 = @parse_url('http://'.@$_SERVER['HTTP_HOST']); + if (@$parsed_url1['host'] && @$parsed_url2['host'] && ($parsed_url1['host'] != $parsed_url2['host'])) { + // include "_offsite" only if nooffsitelink_enabled and if referrer doesn't match the domain of the current server + $this->cache_filename .= '_offsite'; + } + } + + $ParametersString = ''; + if ($this->fltr && is_array($this->fltr)) { + $ParametersString .= '_fltr'.implode('_fltr', $this->fltr); + } + $FilenameParameters1 = array('ar', 'bg', 'bc', 'far', 'sx', 'sy', 'sw', 'sh', 'zc'); + foreach ($FilenameParameters1 as $key) { + if ($this->$key) { + $ParametersString .= '_'.$key.$this->$key; + } + } + $FilenameParameters2 = array('h', 'w', 'wl', 'wp', 'ws', 'hp', 'hs', 'xto', 'ra', 'iar', 'aoe', 'maxb', 'sfn', 'dpi'); + foreach ($FilenameParameters2 as $key) { + if ($this->$key) { + $ParametersString .= '_'.$key.intval($this->$key); + } + } + if ($this->thumbnailFormat == 'jpeg') { + // only JPEG output has variable quality option + $ParametersString .= '_q'.intval($this->thumbnailQuality); + } + $this->DebugMessage('SetCacheFilename() _par set from md5('.$ParametersString.')', __FILE__, __LINE__); + $this->cache_filename .= '_par'.strtolower(md5($ParametersString)); + + if ($this->md5s) { + // source image MD5 hash provided + // do not source image modification date -- + // cached image will be used even if file was modified or removed + } elseif (!$this->config_cache_source_filemtime_ignore_remote && eregi('^(f|ht)tps?\://', $this->src)) { + $this->cache_filename .= '_dat'.intval(phpthumb_functions::filedate_remote($this->src)); + } elseif (!$this->config_cache_source_filemtime_ignore_local && $this->src && !$this->rawImageData) { + $this->cache_filename .= '_dat'.intval(@filemtime($this->sourceFilename)); + } + + $this->cache_filename .= '.'.strtolower($this->thumbnailFormat); + $broad_directories = ''; + for ($i = 0; $i < $this->config_cache_directory_depth; $i++) { + $broad_directories .= DIRECTORY_SEPARATOR.substr($broad_directory_name, 0, $i + 1); + } + + $this->cache_filename = $this->config_cache_directory.$broad_directories.DIRECTORY_SEPARATOR.$this->config_cache_prefix.rawurlencode($this->cache_filename); + return true; + } + + + function SourceImageIsTooLarge($width, $height) { + if (!$this->config_max_source_pixels) { + return false; + } + if (function_exists('memory_get_usage')) { + $available_memory = max(intval(ini_get('memory_limit')), intval(get_cfg_var('memory_limit'))) * 1048576; + $available_memory -= memory_get_usage(); + return (bool) (($width * $height * 5) > $available_memory); + } + return (bool) (($width * $height) > $this->config_max_source_pixels); + } + + function ImageCreateFromFilename($filename) { + // try to create GD image source directly via GD, if possible, + // rather than buffering to memory and creating with ImageCreateFromString + $ImageCreateWasAttempted = false; + $gd_image = false; + + $this->DebugMessage('starting ImageCreateFromFilename('.$filename.')', __FILE__, __LINE__); + if ($filename && ($getimagesizeinfo = @GetImageSize($filename))) { + if (!$this->SourceImageIsTooLarge($getimagesizeinfo[0], $getimagesizeinfo[1])) { + $ImageCreateFromFunction = array( + 1 => 'ImageCreateFromGIF', + 2 => 'ImageCreateFromJPEG', + 3 => 'ImageCreateFromPNG', + 15 => 'ImageCreateFromWBMP', + ); + $this->DebugMessage('ImageCreateFromFilename found ($getimagesizeinfo[2]=='.@$getimagesizeinfo[2].')', __FILE__, __LINE__); + switch (@$getimagesizeinfo[2]) { + case 1: // GIF + case 2: // JPEG + case 3: // PNG + case 15: // WBMP + $ImageCreateFromFunctionName = $ImageCreateFromFunction[$getimagesizeinfo[2]]; + if (function_exists($ImageCreateFromFunctionName)) { + $this->DebugMessage('Calling '.$ImageCreateFromFunctionName.'('.$filename.')', __FILE__, __LINE__); + $ImageCreateWasAttempted = true; + $gd_image = $ImageCreateFromFunctionName($filename); + } else { + $this->DebugMessage('NOT calling '.$ImageCreateFromFunctionName.'('.$filename.') because !function_exists('.$ImageCreateFromFunctionName.')', __FILE__, __LINE__); + } + break; + + case 4: // SWF + case 5: // PSD + case 6: // BMP + case 7: // TIFF (LE) + case 8: // TIFF (BE) + case 9: // JPC + case 10: // JP2 + case 11: // JPX + case 12: // JB2 + case 13: // SWC + case 14: // IFF + case 16: // XBM + $this->DebugMessage('No built-in image creation function for image type "'.@$getimagesizeinfo[2].'" ($getimagesizeinfo[2])', __FILE__, __LINE__); + break; + + default: + $this->DebugMessage('Unknown value for $getimagesizeinfo[2]: "'.@$getimagesizeinfo[2].'"', __FILE__, __LINE__); + break; + } + } else { + $this->DebugMessage('image is '.$getimagesizeinfo[0].'x'.$getimagesizeinfo[1].' and therefore contains more pixels ('.($getimagesizeinfo[0] * $getimagesizeinfo[1]).') than $this->config_max_source_pixels setting ('.$this->config_max_source_pixels.')', __FILE__, __LINE__); + return false; + } + } else { + $this->DebugMessage('empty $filename or GetImageSize('.$filename.') failed', __FILE__, __LINE__); + } + + if (!$gd_image) { + // cannot create from filename, attempt to create source image with ImageCreateFromString, if possible + if ($ImageCreateWasAttempted) { + $this->DebugMessage(@$ImageCreateFromFunctionName.'() was attempted but FAILED', __FILE__, __LINE__); + } + $this->DebugMessage('Populating $rawimagedata', __FILE__, __LINE__); + $rawimagedata = ''; + if ($fp = @fopen($filename, 'rb')) { + $filesize = filesize($filename); + $blocksize = 8192; + $blockreads = ceil($filesize / $blocksize); + for ($i = 0; $i < $blockreads; $i++) { + $rawimagedata .= fread($fp, $blocksize); + } + fclose($fp); + } else { + $this->DebugMessage('cannot fopen('.$filename.')', __FILE__, __LINE__); + } + if ($rawimagedata) { + $this->DebugMessage('attempting ImageCreateFromStringReplacement($rawimagedata ('.strlen($rawimagedata).' bytes), true)', __FILE__, __LINE__); + $gd_image = $this->ImageCreateFromStringReplacement($rawimagedata, true); + } + } + return $gd_image; + } + + function SourceImageToGD() { + if (is_resource($this->gdimg_source)) { + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + $this->DebugMessage('skipping SourceImageToGD() because $this->gdimg_source is already a resource ('.$this->source_width.'x'.$this->source_height.')', __FILE__, __LINE__); + return true; + } + $this->DebugMessage('starting SourceImageToGD()', __FILE__, __LINE__); + + if ($this->ImageMagickThumbnailToGD()) { + + // excellent, we have a thumbnailed source image + $this->DebugMessage('ImageMagickThumbnailToGD() succeeded', __FILE__, __LINE__); + + } elseif (!$this->gdimg_source && $this->rawImageData) { + + if ($this->md5s && ($this->md5s != md5($this->rawImageData))) { + return $this->ErrorImage('$this->md5s != md5($this->rawImageData)'."\n".'"'.$this->md5s.'" != '."\n".'"'.md5($this->rawImageData).'"'); + } + $this->gdimg_source = $this->ImageCreateFromStringReplacement($this->rawImageData); + if (!$this->gdimg_source) { + return $this->ErrorImage('Unknown image type identified by "'.substr($this->rawImageData, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($this->rawImageData, 0, 4)).') in SourceImageToGD()['.__LINE__.']'); + } + + } elseif (!$this->gdimg_source && $this->sourceFilename) { + + if ($this->md5s && ($this->md5s != phpthumb_functions::md5_file_safe($this->sourceFilename))) { + return $this->ErrorImage('$this->md5s != md5(sourceFilename)'."\n".'"'.$this->md5s.'" != '."\n".'"'.phpthumb_functions::md5_file_safe($this->sourceFilename).'"'); + } + switch (@$this->getimagesizeinfo[2]) { + case 1: + case 3: + // GIF or PNG input file may have transparency + $this->is_alpha = true; + break; + } + if (!$this->SourceImageIsTooLarge($this->source_width, $this->source_height)) { + $this->gdimg_source = $this->ImageCreateFromFilename($this->sourceFilename); + } + + } + + while (true) { + if ($this->gdimg_source) { + $this->DebugMessage('Not using EXIF thumbnail data because $this->gdimg_source is already set', __FILE__, __LINE__); + break; + } + if (!$this->exif_thumbnail_data) { + $this->DebugMessage('Not using EXIF thumbnail data because $this->exif_thumbnail_data is empty', __FILE__, __LINE__); + break; + } + if (ini_get('safe_mode')) { + if (!$this->SourceImageIsTooLarge($this->source_width, $this->source_height)) { + $this->DebugMessage('Using EXIF thumbnail data because source image too large and safe_mode enabled', __FILE__, __LINE__); + $this->aoe = true; + } else { + break; + } + } else { + if (!$this->config_use_exif_thumbnail_for_speed) { + $this->DebugMessage('Not using EXIF thumbnail data because $this->config_use_exif_thumbnail_for_speed is FALSE', __FILE__, __LINE__); + break; + } + if (($this->thumbnailCropX != 0) || ($this->thumbnailCropY != 0)) { + $this->DebugMessage('Not using EXIF thumbnail data because source cropping is enabled ('.$this->thumbnailCropX.','.$this->thumbnailCropY.')', __FILE__, __LINE__); + break; + } + if (($this->w > $this->exif_thumbnail_width) || ($this->h > $this->exif_thumbnail_height)) { + $this->DebugMessage('Not using EXIF thumbnail data because EXIF thumbnail is too small ('.$this->exif_thumbnail_width.'x'.$this->exif_thumbnail_height.' vs '.$this->w.'x'.$this->h.')', __FILE__, __LINE__); + break; + } + $source_ar = $this->source_width / $this->source_height; + $exif_ar = $this->exif_thumbnail_width / $this->exif_thumbnail_height; + if (number_format($source_ar, 2) != number_format($exif_ar, 2)) { + $this->DebugMessage('not using EXIF thumbnail because $source_ar != $exif_ar ('.$source_ar.' != '.$exif_ar.')', __FILE__, __LINE__); + break; + } + } + + // EXIF thumbnail exists, and is equal to or larger than destination thumbnail, and will be use as source image + $this->DebugMessage('Trying to use EXIF thumbnail as source image', __FILE__, __LINE__); + + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + + $this->DebugMessage('Successfully using EXIF thumbnail as source image', __FILE__, __LINE__); + $this->gdimg_source = $gdimg_exif_temp; + $this->source_width = $this->exif_thumbnail_width; + $this->source_height = $this->exif_thumbnail_height; + $this->thumbnailCropW = $this->source_width; + $this->thumbnailCropH = $this->source_height; + return true; + + } else { + $this->DebugMessage('$this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false) failed', __FILE__, __LINE__); + } + + break; + } + + if (!$this->gdimg_source) { + $this->DebugMessage('$this->gdimg_source is still empty', __FILE__, __LINE__); + + $this->DebugMessage('ImageMagickThumbnailToGD() failed', __FILE__, __LINE__); + + $imageHeader = ''; + $gd_info = gd_info(); + $GDreadSupport = false; + switch (@$this->getimagesizeinfo[2]) { + case 1: + $imageHeader = 'Content-Type: image/gif'; + $GDreadSupport = (bool) @$gd_info['GIF Read Support']; + break; + case 2: + $imageHeader = 'Content-Type: image/jpeg'; + $GDreadSupport = (bool) @$gd_info['JPG Support']; + break; + case 3: + $imageHeader = 'Content-Type: image/png'; + $GDreadSupport = (bool) @$gd_info['PNG Support']; + break; + } + if ($imageHeader) { + // cannot create image for whatever reason (maybe ImageCreateFromJPEG et al are not available?) + // and ImageMagick is not available either, no choice but to output original (not resized/modified) data and exit + if ($this->config_error_die_on_source_failure) { + $errormessages = array(); + $errormessages[] = 'All attempts to create GD image source failed.'; + if ($this->fatalerror) { + $errormessages[] = $this->fatalerror; + } + if (ini_get('safe_mode')) { + $errormessages[] = 'Safe Mode enabled, therefore ImageMagick is unavailable. (disable Safe Mode if possible)'; + } elseif (!$this->ImageMagickVersion()) { + $errormessages[] = 'ImageMagick is not installed (it is highly recommended that you install it).'; + } + if ($this->SourceImageIsTooLarge($this->getimagesizeinfo[0], $this->getimagesizeinfo[1])) { + $memory_get_usage = (function_exists('memory_get_usage') ? memory_get_usage() : 0); + $errormessages[] = 'Source image is too large ('.$this->getimagesizeinfo[0].'x'.$this->getimagesizeinfo[1].' = '.number_format($this->getimagesizeinfo[0] * $this->getimagesizeinfo[1] / 1000000, 1).'Mpx, max='.number_format($this->config_max_source_pixels / 1000000, 1).'Mpx) for GD creation (either install ImageMagick or increase PHP memory_limit to at least '.ceil(($memory_get_usage + (5 * $this->getimagesizeinfo[0] * $this->getimagesizeinfo[1])) / 1000000).'M).'; + } elseif (!$GDreadSupport) { + $errormessages[] = 'GD does not have read support for "'.$imageHeader.'".'; + } else { + $errormessages[] = 'Source image probably corrupt.'; + } + $this->ErrorImage(implode("\n", $errormessages)); + + } else { + $this->DebugMessage('All attempts to create GD image source failed ('.(ini_get('safe_mode') ? 'Safe Mode enabled, ImageMagick unavailable and source image probably too large for GD': ($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"')).'), cannot generate thumbnail'); + //$this->DebugMessage('All attempts to create GD image source failed ('.($GDreadSupport ? 'source image probably corrupt' : 'GD does not have read support for "'.$imageHeader.'"').'), outputing raw image', __FILE__, __LINE__); + //if (!$this->phpThumbDebug) { + // header($imageHeader); + // echo $this->rawImageData; + // exit; + //} + return false; + } + } + + //switch (substr($this->rawImageData, 0, 2)) { + // case 'BM': + switch (@$this->getimagesizeinfo[2]) { + case 6: + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.bmp.php')) { + ob_end_clean(); + return $this->ErrorImage('include_once('.dirname(__FILE__).'/phpthumb.bmp.php) failed'); + } + ob_end_clean(); + if ($fp = @fopen($this->sourceFilename, 'rb')) { + $this->rawImageData = ''; + while (!feof($fp)) { + $this->rawImageData .= fread($fp, 32768); + } + fclose($fp); + } + $phpthumb_bmp = new phpthumb_bmp(); + if ($this->gdimg_source = $phpthumb_bmp->phpthumb_bmp2gd($this->rawImageData, (phpthumb_functions::gd_version() >= 2.0))) { + $this->DebugMessage('$phpthumb_bmp->phpthumb_bmp2gd() succeeded', __FILE__, __LINE__); + break; + } + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on BMP source conversion' : 'phpthumb_bmp2gd() failed'); + break; + //} + //switch (substr($this->rawImageData, 0, 4)) { + // case 'II'."\x2A\x00": + // case 'MM'."\x00\x2A": + case 7: + case 8: + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on TIFF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support TIFF source images without it'); + break; + + //case "\xD7\xCD\xC6\x9A": + // return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it'); + // break; + } + + if (!$this->gdimg_source) { + $HeaderFourBytes = ''; + if ($fp = @fopen($this->sourceFilename, 'rb')) { + $HeaderFourBytes = fread($fp, 4); + fclose($fp); + } + if ($HeaderFourBytes == "\xD7\xCD\xC6\x9A") { // WMF + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick failed on WMF source conversion' : 'ImageMagick is unavailable and phpThumb() does not support WMF source images without it'); + } elseif ($HeaderFourBytes == '%PDF') { // "%PDF" + return $this->ErrorImage($this->ImageMagickVersion() ? 'ImageMagick and GhostScript are both required for PDF source images; GhostScript may not be properly configured' : 'ImageMagick and/or GhostScript are unavailable and phpThumb() does not support PDF source images without them'); + } elseif (substr($HeaderFourBytes, 0, 3) == "\xFF\xD8\xFF") { // JPEG + return $this->ErrorImage('Image is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting'); + } elseif ($HeaderFourBytes == '%PNG') { // "%PNG" + return $this->ErrorImage('Image is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting'); + } elseif (substr($HeaderFourBytes, 0, 3) == 'GIF') { // GIF + return $this->ErrorImage('Image is too large for PHP-GD memory_limit, please install ImageMagick or increase php.ini memory_limit setting'); + } + return $this->ErrorImage('Unknown image type identified by "'.substr($HeaderFourBytes, 0, 4).'" ('.phpthumb_functions::HexCharDisplay(substr($HeaderFourBytes, 0, 4)).') in SourceImageToGD()['.__LINE__.']'); + + } + } + + if (!$this->gdimg_source) { + if ($gdimg_exif_temp = $this->ImageCreateFromStringReplacement($this->exif_thumbnail_data, false)) { + $this->DebugMessage('All other attempts failed, but successfully using EXIF thumbnail as source image', __FILE__, __LINE__); + $this->gdimg_source = $gdimg_exif_temp; + // override allow-enlarging setting if EXIF thumbnail is the only source available + // otherwise thumbnails larger than the EXIF thumbnail will be created at EXIF size + $this->aoe = true; + return true; + } + return false; + } + + $this->source_width = ImageSX($this->gdimg_source); + $this->source_height = ImageSY($this->gdimg_source); + return true; + } + + + function phpThumbDebugVarDump($var) { + if (is_null($var)) { + return 'NULL'; + } elseif (is_bool($var)) { + return ($var ? 'TRUE' : 'FALSE'); + } elseif (is_string($var)) { + return 'string('.strlen($var).')'.str_repeat(' ', max(0, 3 - strlen(strlen($var)))).' "'.$var.'"'; + } elseif (is_int($var)) { + return 'integer '.$var; + } elseif (is_float($var)) { + return 'float '.$var; + } elseif (is_array($var)) { + ob_start(); + var_dump($var); + $vardumpoutput = ob_get_contents(); + ob_end_clean(); + return strtr($vardumpoutput, "\n\r\t", ' '); + } + return gettype($var); + } + + function phpThumbDebug($level='') { + if ($level && ($this->phpThumbDebug !== $level)) { + return true; + } + if ($this->config_disable_debug) { + return $this->ErrorImage('phpThumbDebug disabled'); + } + + $FunctionsExistance = array('exif_thumbnail', 'gd_info', 'image_type_to_mime_type', 'ImageCopyResampled', 'ImageCopyResized', 'ImageCreate', 'ImageCreateFromString', 'ImageCreateTrueColor', 'ImageIsTrueColor', 'ImageRotate', 'ImageTypes', 'version_compare', 'ImageCreateFromGIF', 'ImageCreateFromJPEG', 'ImageCreateFromPNG', 'ImageCreateFromWBMP', 'ImageCreateFromXBM', 'ImageCreateFromXPM', 'ImageCreateFromString', 'ImageCreateFromGD', 'ImageCreateFromGD2', 'ImageCreateFromGD2Part', 'ImageJPEG', 'ImageGIF', 'ImagePNG', 'ImageWBMP'); + $ParameterNames = array('src', 'new', 'w', 'h', 'f', 'q', 'sx', 'sy', 'sw', 'sh', 'far', 'bg', 'bc', 'file', 'goto', 'err', 'xto', 'ra', 'ar', 'aoe', 'iar', 'maxb'); + $ConfigVariableNames = array('document_root', 'temp_directory', 'output_format', 'output_maxwidth', 'output_maxheight', 'error_message_image_default', 'error_bgcolor', 'error_textcolor', 'error_fontsize', 'error_die_on_error', 'error_silent_die_on_error', 'error_die_on_source_failure', 'nohotlink_enabled', 'nohotlink_valid_domains', 'nohotlink_erase_image', 'nohotlink_text_message', 'nooffsitelink_enabled', 'nooffsitelink_valid_domains', 'nooffsitelink_require_refer', 'nooffsitelink_erase_image', 'nooffsitelink_text_message', 'high_security_enabled', 'allow_src_above_docroot', 'allow_src_above_phpthumb', 'allow_parameter_file', 'allow_parameter_goto', 'max_source_pixels', 'use_exif_thumbnail_for_speed', 'border_hexcolor', 'background_hexcolor', 'ttf_directory', 'disable_pathinfo_parsing', 'disable_imagecopyresampled'); + $OtherVariableNames = array('phpThumbDebug', 'thumbnailQuality', 'thumbnailFormat', 'gdimg_output', 'gdimg_source', 'sourceFilename', 'source_width', 'source_height', 'thumbnailCropX', 'thumbnailCropY', 'thumbnailCropW', 'thumbnailCropH', 'exif_thumbnail_width', 'exif_thumbnail_height', 'exif_thumbnail_type', 'thumbnail_width', 'thumbnail_height', 'thumbnail_image_width', 'thumbnail_image_height'); + + $DebugOutput = array(); + $DebugOutput[] = 'phpThumb() version = '.$this->phpthumb_version; + $DebugOutput[] = 'phpversion() = '.@phpversion(); + $DebugOutput[] = 'PHP_OS = '.PHP_OS; + $DebugOutput[] = '__FILE__ = '.__FILE__; + $DebugOutput[] = 'realpath(.) = '.@realpath('.'); + $DebugOutput[] = '$_SERVER[PHP_SELF] = '.@$_SERVER['PHP_SELF']; + $DebugOutput[] = '$_SERVER[HOST_NAME] = '.@$_SERVER['HOST_NAME']; + $DebugOutput[] = '$_SERVER[HTTP_REFERER] = '.@$_SERVER['HTTP_REFERER']; + $DebugOutput[] = '$_SERVER[QUERY_STRING] = '.@$_SERVER['QUERY_STRING']; + $DebugOutput[] = '$_SERVER[PATH_INFO] = '.@$_SERVER['PATH_INFO']; + $DebugOutput[] = '$_SERVER[DOCUMENT_ROOT] = '.@$_SERVER['DOCUMENT_ROOT']; + $DebugOutput[] = 'getenv(DOCUMENT_ROOT) = '.@getenv('DOCUMENT_ROOT'); + $DebugOutput[] = ''; + + $DebugOutput[] = 'get_magic_quotes_gpc() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_gpc()); + $DebugOutput[] = 'get_magic_quotes_runtime() = '.$this->phpThumbDebugVarDump(@get_magic_quotes_runtime()); + $DebugOutput[] = 'error_reporting() = '.$this->phpThumbDebugVarDump(error_reporting()); + $DebugOutput[] = 'ini_get(error_reporting) = '.$this->phpThumbDebugVarDump(@ini_get('error_reporting')); + $DebugOutput[] = 'ini_get(display_errors) = '.$this->phpThumbDebugVarDump(@ini_get('display_errors')); + $DebugOutput[] = 'ini_get(allow_url_fopen) = '.$this->phpThumbDebugVarDump(@ini_get('allow_url_fopen')); + $DebugOutput[] = 'ini_get(disable_functions) = '.$this->phpThumbDebugVarDump(@ini_get('disable_functions')); + $DebugOutput[] = 'ini_get(safe_mode) = '.$this->phpThumbDebugVarDump(@ini_get('safe_mode')); + $DebugOutput[] = 'ini_get(open_basedir) = '.$this->phpThumbDebugVarDump(@ini_get('open_basedir')); + $DebugOutput[] = 'ini_get(max_execution_time) = '.$this->phpThumbDebugVarDump(@ini_get('max_execution_time')); + $DebugOutput[] = 'ini_get(memory_limit) = '.$this->phpThumbDebugVarDump(@ini_get('memory_limit')); + $DebugOutput[] = 'get_cfg_var(memory_limit) = '.$this->phpThumbDebugVarDump(@get_cfg_var('memory_limit')); + $DebugOutput[] = 'memory_get_usage() = '.(function_exists('memory_get_usage') ? $this->phpThumbDebugVarDump(@memory_get_usage()) : 'n/a'); + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->config_prefer_imagemagick = '.$this->phpThumbDebugVarDump($this->config_prefer_imagemagick); + $DebugOutput[] = '$this->config_imagemagick_path = '.$this->phpThumbDebugVarDump($this->config_imagemagick_path); + $DebugOutput[] = '$this->ImageMagickWhichConvert() = '.$this->ImageMagickWhichConvert(); + $IMpathUsed = ($this->config_imagemagick_path ? $this->config_imagemagick_path : $this->ImageMagickWhichConvert()); + $DebugOutput[] = '[actual ImageMagick path used] = '.$this->phpThumbDebugVarDump($IMpathUsed); + $DebugOutput[] = 'file_exists([actual ImageMagick path used]) = '.$this->phpThumbDebugVarDump(@file_exists($IMpathUsed)); + $DebugOutput[] = 'ImageMagickVersion(false) = '.$this->ImageMagickVersion(false); + $DebugOutput[] = 'ImageMagickVersion(true) = '.$this->ImageMagickVersion(true); + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->config_cache_directory = '.$this->phpThumbDebugVarDump($this->config_cache_directory); + $DebugOutput[] = '$this->config_cache_directory_depth = '.$this->phpThumbDebugVarDump($this->config_cache_directory_depth); + $DebugOutput[] = '$this->config_cache_disable_warning = '.$this->phpThumbDebugVarDump($this->config_cache_disable_warning); + $DebugOutput[] = '$this->config_cache_maxage = '.$this->phpThumbDebugVarDump($this->config_cache_maxage); + $DebugOutput[] = '$this->config_cache_maxsize = '.$this->phpThumbDebugVarDump($this->config_cache_maxsize); + $DebugOutput[] = '$this->config_cache_maxfiles = '.$this->phpThumbDebugVarDump($this->config_cache_maxfiles); + $DebugOutput[] = '$this->config_cache_force_passthru = '.$this->phpThumbDebugVarDump($this->config_cache_force_passthru); + $DebugOutput[] = '$this->cache_filename = '.$this->phpThumbDebugVarDump($this->cache_filename); + $DebugOutput[] = 'is_readable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(@is_readable($this->config_cache_directory)); + $DebugOutput[] = 'is_writable($this->config_cache_directory) = '.$this->phpThumbDebugVarDump(@is_writable($this->config_cache_directory)); + $DebugOutput[] = 'is_readable($this->cache_filename) = '.$this->phpThumbDebugVarDump(@is_readable($this->cache_filename)); + $DebugOutput[] = 'is_writable($this->cache_filename) = '.(@file_exists($this->cache_filename) ? $this->phpThumbDebugVarDump(@is_writable($this->cache_filename)) : 'n/a'); + $DebugOutput[] = ''; + + foreach ($ConfigVariableNames as $varname) { + $varname = 'config_'.$varname; + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 37, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + foreach ($OtherVariableNames as $varname) { + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 27, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = 'strlen($this->rawImageData) = '.strlen(@$this->rawImageData); + $DebugOutput[] = 'strlen($this->exif_thumbnail_data) = '.strlen(@$this->exif_thumbnail_data); + $DebugOutput[] = ''; + + foreach ($ParameterNames as $varname) { + $value = $this->$varname; + $DebugOutput[] = '$this->'.str_pad($varname, 4, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + foreach ($FunctionsExistance as $functionname) { + $DebugOutput[] = 'builtin_function_exists('.$functionname.')'.str_repeat(' ', 23 - strlen($functionname)).' = '.$this->phpThumbDebugVarDump(phpthumb_functions::builtin_function_exists($functionname)); + } + $DebugOutput[] = ''; + + $gd_info = gd_info(); + foreach ($gd_info as $key => $value) { + $DebugOutput[] = 'gd_info.'.str_pad($key, 34, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + $exif_info = phpthumb_functions::exif_info(); + foreach ($exif_info as $key => $value) { + $DebugOutput[] = 'exif_info.'.str_pad($key, 26, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + $DebugOutput[] = ''; + + if ($ApacheLookupURIarray = phpthumb_functions::ApacheLookupURIarray(dirname(@$_SERVER['PHP_SELF']))) { + foreach ($ApacheLookupURIarray as $key => $value) { + $DebugOutput[] = 'ApacheLookupURIarray.'.str_pad($key, 15, ' ', STR_PAD_RIGHT).' = '.$this->phpThumbDebugVarDump($value); + } + } else { + $DebugOutput[] = 'ApacheLookupURIarray() -- FAILED'; + } + $DebugOutput[] = ''; + + if (isset($_GET) && is_array($_GET)) { + foreach ($_GET as $key => $value) { + $DebugOutput[] = '$_GET['.$key.']'.str_repeat(' ', 30 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); + } + } + if (isset($_POST) && is_array($_POST)) { + foreach ($_POST as $key => $value) { + $DebugOutput[] = '$_POST['.$key.']'.str_repeat(' ', 29 - strlen($key)).'= '.$this->phpThumbDebugVarDump($value); + } + } + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->debugmessages:'; + foreach ($this->debugmessages as $errorstring) { + $DebugOutput[] = ' * '.$errorstring; + } + $DebugOutput[] = ''; + + $DebugOutput[] = '$this->debugtiming:'; + foreach ($this->debugtiming as $timestamp => $timingstring) { + $DebugOutput[] = ' * '.$timestamp.' '.$timingstring; + } + $DebugOutput[] = ' * Total processing time: '.number_format(max(array_keys($this->debugtiming)) - min(array_keys($this->debugtiming)), 6); + + $this->f = (isset($_GET['f']) ? $_GET['f'] : $this->f); // debug modes 0-2 don't recognize text mode otherwise + return $this->ErrorImage(implode("\n", $DebugOutput), 700, 500, true); + } + + function ErrorImage($text, $width=0, $height=0, $forcedisplay=false) { + $width = ($width ? $width : $this->config_error_image_width); + $height = ($height ? $height : $this->config_error_image_height); + + $text = 'phpThumb() v'.$this->phpthumb_version."\n\n".$text; + if ($this->config_disable_debug) { + $text = 'Error messages disabled'; + } + + $this->DebugMessage($text, __FILE__, __LINE__); + if ($this->phpThumbDebug && !$forcedisplay) { + return false; + } + if (!$this->config_error_die_on_error && !$forcedisplay) { + $this->fatalerror = $text; + return false; + } + if ($this->config_error_silent_die_on_error) { + exit; + } + if ($this->err || $this->config_error_message_image_default) { + // Show generic custom error image instead of error message + // for use on production sites where you don't want debug messages + if ($this->err == 'showerror') { + // fall through and actually show error message even if default error image is set + } else { + header('Location: '.($this->err ? $this->err : $this->config_error_message_image_default)); + exit; + } + } + $this->setOutputFormat(); + if (!$this->thumbnailFormat || (phpthumb_functions::gd_version() < 1)) { + $this->thumbnailFormat = 'text'; + } + if (@$this->thumbnailFormat == 'text') { + // bypass all GD functions and output text error message + die('
    '.$text.'
    '); + } + + $FontWidth = ImageFontWidth($this->config_error_fontsize); + $FontHeight = ImageFontHeight($this->config_error_fontsize); + + $LinesOfText = explode("\n", @wordwrap($text, floor($width / $FontWidth), "\n", true)); + $height = max($height, count($LinesOfText) * $FontHeight); + + $headers_file = ''; + $headers_line = ''; + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=') && headers_sent($headers_file, $headers_line)) { + + echo "\n".'**Headers already sent in file "'.$headers_file.'" on line "'.$headers_line.'", dumping error message as text:**
    '."\n\n".$text."\n".'
    '; + + } elseif (headers_sent()) { + + echo "\n".'**Headers already sent, dumping error message as text:**
    '."\n\n".$text."\n".'
    '; + + } elseif ($gdimg_error = ImageCreate($width, $height)) { + + $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_bgcolor, true); + $text_color = phpthumb_functions::ImageHexColorAllocate($gdimg_error, $this->config_error_textcolor, true); + ImageFilledRectangle($gdimg_error, 0, 0, $width, $height, $background_color); + $lineYoffset = 0; + foreach ($LinesOfText as $line) { + ImageString($gdimg_error, $this->config_error_fontsize, 2, $lineYoffset, $line, $text_color); + $lineYoffset += $FontHeight; + } + if (function_exists('ImageTypes')) { + $imagetypes = ImageTypes(); + if ($imagetypes & IMG_PNG) { + header('Content-Type: image/png'); + ImagePNG($gdimg_error); + } elseif ($imagetypes & IMG_GIF) { + header('Content-Type: image/gif'); + ImageGIF($gdimg_error); + } elseif ($imagetypes & IMG_JPG) { + header('Content-Type: image/jpeg'); + ImageJPEG($gdimg_error); + } elseif ($imagetypes & IMG_WBMP) { + header('Content-Type: image/vnd.wap.wbmp'); + ImageWBMP($gdimg_error); + } + } + ImageDestroy($gdimg_error); + + } + if (!headers_sent()) { + echo "\n".'**Failed to send graphical error image, dumping error message as text:**
    '."\n\n".$text; + } + exit; + return true; + } + + function ImageCreateFromStringReplacement(&$RawImageData, $DieOnErrors=false) { + // there are serious bugs in the non-bundled versions of GD which may cause + // PHP to segfault when calling ImageCreateFromString() - avoid if at all possible + // when not using a bundled version of GD2 + if (!phpthumb_functions::gd_version()) { + if ($DieOnErrors) { + if (!headers_sent()) { + // base64-encoded error image in GIF format + $ERROR_NOGD = 'R0lGODlhIAAgALMAAAAAABQUFCQkJDY2NkZGRldXV2ZmZnJycoaGhpSUlKWlpbe3t8XFxdXV1eTk5P7+/iwAAAAAIAAgAAAE/vDJSau9WILtTAACUinDNijZtAHfCojS4W5H+qxD8xibIDE9h0OwWaRWDIljJSkUJYsN4bihMB8th3IToAKs1VtYM75cyV8sZ8vygtOE5yMKmGbO4jRdICQCjHdlZzwzNW4qZSQmKDaNjhUMBX4BBAlmMywFSRWEmAI6b5gAlhNxokGhooAIK5o/pi9vEw4Lfj4OLTAUpj6IabMtCwlSFw0DCKBoFqwAB04AjI54PyZ+yY3TD0ss2YcVmN/gvpcu4TOyFivWqYJlbAHPpOntvxNAACcmGHjZzAZqzSzcq5fNjxFmAFw9iFRunD1epU6tsIPmFCAJnWYE0FURk7wJDA0MTKpEzoWAAskiAAA7'; + header('Content-Type: image/gif'); + echo base64_decode($ERROR_NOGD); + } else { + echo '*** ERROR: No PHP-GD support available ***'; + } + exit; + } else { + $this->DebugMessage('ImageCreateFromStringReplacement() failed: gd_version says "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + } + if (phpthumb_functions::gd_is_bundled()) { + $this->DebugMessage('ImageCreateFromStringReplacement() calling built-in ImageCreateFromString()', __FILE__, __LINE__); + return @ImageCreateFromString($RawImageData); + } + if (ini_get('safe_mode')) { + $this->DebugMessage('ImageCreateFromStringReplacement() failed: cannot create temp file in SAFE_MODE', __FILE__, __LINE__); + return false; + } + + switch (substr($RawImageData, 0, 3)) { + case 'GIF': + $ICFSreplacementFunctionName = 'ImageCreateFromGIF'; + break; + case "\xFF\xD8\xFF": + $ICFSreplacementFunctionName = 'ImageCreateFromJPEG'; + break; + case "\x89".'PN': + $ICFSreplacementFunctionName = 'ImageCreateFromPNG'; + break; + default: + $this->DebugMessage('ImageCreateFromStringReplacement() failed: unknown fileformat signature "'.phpthumb_functions::HexCharDisplay(substr($RawImageData, 0, 3)).'"', __FILE__, __LINE__); + return false; + break; + } + if ($tempnam = $this->phpThumb_tempnam()) { + if ($fp_tempnam = @fopen($tempnam, 'wb')) { + fwrite($fp_tempnam, $RawImageData); + fclose($fp_tempnam); + if (($ICFSreplacementFunctionName == 'ImageCreateFromGIF') && !function_exists($ICFSreplacementFunctionName)) { + + // Need to create from GIF file, but ImageCreateFromGIF does not exist + ob_start(); + if (!@include_once(dirname(__FILE__).'/phpthumb.gif.php')) { + $ErrorMessage = 'Failed to include required file "'.dirname(__FILE__).'/phpthumb.gif.php" in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + ob_end_clean(); + // gif_loadFileToGDimageResource() cannot read from raw data, write to file first + if ($tempfilename = $this->phpThumb_tempnam()) { + if ($fp_tempfile = @fopen($tempfilename, 'wb')) { + fwrite($fp_tempfile, $RawImageData); + fclose($fp_tempfile); + $gdimg_source = gif_loadFileToGDimageResource($tempfilename); + $this->DebugMessage('gif_loadFileToGDimageResource('.$tempfilename.') completed', __FILE__, __LINE__); + unlink($tempfilename); + return $gdimg_source; + break; + } else { + $ErrorMessage = 'Failed to open tempfile in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + } else { + $ErrorMessage = 'Failed to open generate tempfile name in '.__FILE__.' on line '.__LINE__; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + + } elseif (function_exists($ICFSreplacementFunctionName) && ($gdimg_source = @$ICFSreplacementFunctionName($tempnam))) { + + // great + $this->DebugMessage($ICFSreplacementFunctionName.'('.$tempnam.') succeeded', __FILE__, __LINE__); + unlink($tempnam); + return $gdimg_source; + + } else { + + // GD functions not available, or failed to create image + $this->DebugMessage($ICFSreplacementFunctionName.'('.$tempnam.') '.(function_exists($ICFSreplacementFunctionName) ? 'failed' : 'does not exist'), __FILE__, __LINE__); + if (isset($_GET['phpThumbDebug'])) { + $this->phpThumbDebug(); + } + + } + } else { + $ErrorMessage = 'Failed to fopen('.$tempnam.', "wb") in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; + $this->DebugMessage($ErrorMessage, __FILE__, __LINE__); + } + @unlink($tempnam); + } else { + $ErrorMessage = 'Failed to generate phpThumb_tempnam() in '.__FILE__.' on line '.__LINE__."\n".'You may need to set $PHPTHUMB_CONFIG[temp_directory] in phpThumb.config.php'; + } + if ($DieOnErrors && $ErrorMessage) { + return $this->ErrorImage($ErrorMessage); + } + return false; + } + + function ImageResizeFunction(&$dst_im, &$src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH) { + $this->DebugMessage('ImageResizeFunction($o, $s, '.$dstX.', '.$dstY.', '.$srcX.', '.$srcY.', '.$dstW.', '.$dstH.', '.$srcW.', '.$srcH.')', __FILE__, __LINE__); + if (phpthumb_functions::gd_version() >= 2.0) { + if ($this->config_disable_imagecopyresampled) { + return phpthumb_functions::ImageCopyResampleBicubic($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + return ImageCopyResampled($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + return ImageCopyResized($dst_im, $src_im, $dstX, $dstY, $srcX, $srcY, $dstW, $dstH, $srcW, $srcH); + } + + function phpThumb_tempnam() { + $tempnam = realpath(tempnam($this->config_temp_directory, 'pThumb')); + $this->DebugMessage('phpThumb_tempnam() returning "'.$tempnam.'"', __FILE__, __LINE__); + return $tempnam; + } + + function DebugMessage($message, $file='', $line='') { + $this->debugmessages[] = $message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); + return true; + } + + function DebugTimingMessage($message, $file='', $line='', $timestamp=0) { + if (!$timestamp) { + $timestamp = array_sum(explode(' ', microtime())); + } + $this->debugtiming[number_format($timestamp, 6, '.', '')] = ': '.$message.($file ? ' in file "'.(basename($file) ? basename($file) : $file).'"' : '').($line ? ' on line '.$line : ''); + return true; + } + +} + +?> \ No newline at end of file diff --git a/common/phpThumb/phpthumb.filters.php b/common/phpThumb/phpthumb.filters.php new file mode 100644 index 0000000..11b67c8 --- /dev/null +++ b/common/phpThumb/phpthumb.filters.php @@ -0,0 +1,1377 @@ + // +// available at http://phpthumb.sourceforge.net /// +////////////////////////////////////////////////////////////// +/// // +// phpthumb.filters.php - image processing filter functions // +// /// +////////////////////////////////////////////////////////////// + +class phpthumb_filters { + + var $phpThumbObject = null; + + function phpthumb_filters() { + return true; + } + + function ApplyMask(&$gdimg_mask, &$gdimg_image) { + if (phpthumb_functions::gd_version() < 2) { + $this->DebugMessage('Skipping ApplyMask() because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + return false; + } + if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=')) { + + $this->DebugMessage('Using alpha ApplyMask() technique', __FILE__, __LINE__); + if ($gdimg_mask_resized = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { + + ImageCopyResampled($gdimg_mask_resized, $gdimg_mask, 0, 0, 0, 0, ImageSX($gdimg_image), ImageSY($gdimg_image), ImageSX($gdimg_mask), ImageSY($gdimg_mask)); + if ($gdimg_mask_blendtemp = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_image), ImageSY($gdimg_image))) { + + $color_background = ImageColorAllocate($gdimg_mask_blendtemp, 0, 0, 0); + ImageFilledRectangle($gdimg_mask_blendtemp, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp), $color_background); + ImageAlphaBlending($gdimg_mask_blendtemp, false); + ImageSaveAlpha($gdimg_mask_blendtemp, true); + for ($x = 0; $x < ImageSX($gdimg_image); $x++) { + for ($y = 0; $y < ImageSY($gdimg_image); $y++) { + //$RealPixel = phpthumb_functions::GetPixelColor($gdimg_mask_blendtemp, $x, $y); + $RealPixel = phpthumb_functions::GetPixelColor($gdimg_image, $x, $y); + $MaskPixel = phpthumb_functions::GrayscalePixel(phpthumb_functions::GetPixelColor($gdimg_mask_resized, $x, $y)); + $MaskAlpha = 127 - (floor($MaskPixel['red'] / 2) * (1 - ($RealPixel['alpha'] / 127))); + $newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_mask_blendtemp, $RealPixel['red'], $RealPixel['green'], $RealPixel['blue'], $MaskAlpha); + ImageSetPixel($gdimg_mask_blendtemp, $x, $y, $newcolor); + } + } + ImageAlphaBlending($gdimg_image, false); + ImageSaveAlpha($gdimg_image, true); + ImageCopy($gdimg_image, $gdimg_mask_blendtemp, 0, 0, 0, 0, ImageSX($gdimg_mask_blendtemp), ImageSY($gdimg_mask_blendtemp)); + ImageDestroy($gdimg_mask_blendtemp); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + ImageDestroy($gdimg_mask_resized); + + } else { + $this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + + } else { + // alpha merging requires PHP v4.3.2+ + $this->DebugMessage('Skipping ApplyMask() technique because PHP is v"'.phpversion().'"', __FILE__, __LINE__); + } + return true; + } + + + function Bevel(&$gdimg, $width, $hexcolor1, $hexcolor2) { + $width = ($width ? $width : 5); + $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); + $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); + + ImageAlphaBlending($gdimg, true); + for ($i = 0; $i < $width; $i++) { + $alpha = round(($i / $width) * 127); + $color1[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1, false, $alpha); + $color2[$i] = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2, false, $alpha); + + ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1[$i]); // left + ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1[$i]); // top + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2[$i]); // right + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2[$i]); // bottom + } + return true; + } + + + function Blur(&$gdimg, $radius=0.5) { + // Taken from Torstein Hnsi's phpUnsharpMask (see phpthumb.unsharp.php) + + $radius = round(max(0, min($radius, 50)) * 2); + if (!$radius) { + return false; + } + + $w = ImageSX($gdimg); + $h = ImageSY($gdimg); + if ($imgBlur = ImageCreateTrueColor($w, $h)) { + // Gaussian blur matrix: + // 1 2 1 + // 2 4 2 + // 1 2 1 + + // Move copies of the image around one pixel at the time and merge them with weight + // according to the matrix. The same matrix is simply repeated for higher radii. + for ($i = 0; $i < $radius; $i++) { + ImageCopy ($imgBlur, $gdimg, 0, 0, 1, 1, $w - 1, $h - 1); // up left + ImageCopyMerge($imgBlur, $gdimg, 1, 1, 0, 0, $w, $h, 50.00000); // down right + ImageCopyMerge($imgBlur, $gdimg, 0, 1, 1, 0, $w - 1, $h, 33.33333); // down left + ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 1, $w, $h - 1, 25.00000); // up right + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 1, 0, $w - 1, $h, 33.33333); // left + ImageCopyMerge($imgBlur, $gdimg, 1, 0, 0, 0, $w, $h, 25.00000); // right + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 1, $w, $h - 1, 20.00000); // up + ImageCopyMerge($imgBlur, $gdimg, 0, 1, 0, 0, $w, $h, 16.666667); // down + ImageCopyMerge($imgBlur, $gdimg, 0, 0, 0, 0, $w, $h, 50.000000); // center + ImageCopy ($gdimg, $imgBlur, 0, 0, 0, 0, $w, $h); + } + return true; + } + return false; + } + + + function BlurGaussian(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GAUSSIAN_BLUR)', __FILE__, __LINE__); + // fall through and try it the hard way + } + $this->DebugMessage('FAILED: phpthumb_filters::BlurGaussian($gdimg) [using phpthumb_filters::Blur() instead]', __FILE__, __LINE__); + return phpthumb_filters::Blur($gdimg, 0.5); + } + + + function BlurSelective(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SELECTIVE_BLUR)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::BlurSelective($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Brightness(&$gdimg, $amount=0) { + if ($amount == 0) { + return true; + } + $amount = max(-255, min(255, $amount)); + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_BRIGHTNESS, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + + $scaling = (255 - abs($amount)) / 255; + $baseamount = (($amount > 0) ? $amount : 0); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + foreach ($OriginalPixel as $key => $value) { + $NewPixel[$key] = round($baseamount + ($OriginalPixel[$key] * $scaling)); + } + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Contrast(&$gdimg, $amount=0) { + if ($amount == 0) { + return true; + } + $amount = max(-255, min(255, $amount)); + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_CONTRAST, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_CONTRAST, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + + if ($amount > 0) { + $scaling = 1 + ($amount / 255); + } else { + $scaling = (255 - abs($amount)) / 255; + } + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + foreach ($OriginalPixel as $key => $value) { + $NewPixel[$key] = min(255, max(0, round($OriginalPixel[$key] * $scaling))); + } + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + } + + + function Colorize(&$gdimg, $amount, $targetColor) { + $amount = (is_numeric($amount) ? $amount : 25); + $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'gray'); + + if ($amount == 0) { + return true; + } + + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if ($targetColor == 'gray') { + $targetColor = '808080'; + } + $r = substr($targetColor, 0, 2); + $g = substr($targetColor, 2, 2); + $b = substr($targetColor, 4, 2); + if (ImageFilter($gdimg, IMG_FILTER_COLORIZE, $r, $g, $b)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_COLORIZE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + + // overridden below for grayscale + if ($targetColor != 'gray') { + $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); + $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); + $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); + } + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + if ($targetColor == 'gray') { + $TargetPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + } + foreach ($TargetPixel as $key => $value) { + $NewPixel[$key] = round(max(0, min(255, ($OriginalPixel[$key] * ((100 - $amount) / 100)) + ($TargetPixel[$key] * ($amount / 100))))); + } + //$newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); + $newColor = ImageColorAllocate($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Crop(&$gdimg, $left=0, $right=0, $top=0, $bottom=0) { + if (!$left && !$right && !$top && !$bottom) { + return true; + } + $oldW = ImageSX($gdimg); + $oldH = ImageSY($gdimg); + if (($left > 0) && ($left < 1)) { $left = round($left * $oldW); } + if (($right > 0) && ($right < 1)) { $right = round($right * $oldW); } + if (($top > 0) && ($top < 1)) { $top = round($top * $oldH); } + if (($bottom > 0) && ($bottom < 1)) { $bottom = round($bottom * $oldH); } + $right = min($oldW - $left - 1, $right); + $bottom = min($oldH - $top - 1, $bottom); + $newW = $oldW - $left - $right; + $newH = $oldH - $top - $bottom; + + if ($imgCropped = ImageCreateTrueColor($newW, $newH)) { + ImageCopy($imgCropped, $gdimg, 0, 0, $left, $top, $newW, $newH); + if ($gdimg = ImageCreateTrueColor($newW, $newH)) { + ImageCopy($gdimg, $imgCropped, 0, 0, 0, 0, $newW, $newH); + ImageDestroy($imgCropped); + return true; + } + ImageDestroy($imgCropped); + } + return false; + } + + + function Desaturate(&$gdimg, $amount, $color='') { + if ($amount == 0) { + return true; + } + return phpthumb_filters::Colorize($gdimg, $amount, (phpthumb_functions::IsHexColor($color) ? $color : 'gray')); + } + + + function DropShadow(&$gdimg, $distance, $width, $hexcolor, $angle, $fade) { + if (phpthumb_functions::gd_version() < 2) { + return false; + } + $distance = ($distance ? $distance : 10); + $width = ($width ? $width : 10); + $hexcolor = ($hexcolor ? $hexcolor : '000000'); + $angle = ($angle ? $angle : 225); + $fade = ($fade ? $fade : 1); + + $width_shadow = cos(deg2rad($angle)) * ($distance + $width); + $height_shadow = sin(deg2rad($angle)) * ($distance + $width); + + $scaling = min(ImageSX($gdimg) / (ImageSX($gdimg) + abs($width_shadow)), ImageSY($gdimg) / (ImageSY($gdimg) + abs($height_shadow))); + + for ($i = 0; $i < $width; $i++) { + $WidthAlpha[$i] = (abs(($width / 2) - $i) / $width) * $fade; + $Offset['x'] = cos(deg2rad($angle)) * ($distance + $i); + $Offset['y'] = sin(deg2rad($angle)) * ($distance + $i); + } + + $tempImageWidth = ImageSX($gdimg) + abs($Offset['x']); + $tempImageHeight = ImageSY($gdimg) + abs($Offset['y']); + + if ($gdimg_dropshadow_temp = phpthumb_functions::ImageCreateFunction($tempImageWidth, $tempImageHeight)) { + + ImageAlphaBlending($gdimg_dropshadow_temp, false); + ImageSaveAlpha($gdimg_dropshadow_temp, true); + $transparent1 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, 0, 0, 0, 127); + ImageFill($gdimg_dropshadow_temp, 0, 0, $transparent1); + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $PixelMap[$x][$y] = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + } + } + for ($x = 0; $x < $tempImageWidth; $x++) { + for ($y = 0; $y < $tempImageHeight; $y++) { + //for ($i = 0; $i < $width; $i++) { + for ($i = 0; $i < 1; $i++) { + if (!isset($PixelMap[$x][$y]['alpha']) || ($PixelMap[$x][$y]['alpha'] > 0)) { + if (isset($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']) && ($PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha'] < 127)) { + $thisColor = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor, false, $PixelMap[$x + $Offset['x']][$y + $Offset['y']]['alpha']); + ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); + } + } + } + } + } + + ImageAlphaBlending($gdimg_dropshadow_temp, true); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + if ($PixelMap[$x][$y]['alpha'] < 127) { + $thisColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_dropshadow_temp, $PixelMap[$x][$y]['red'], $PixelMap[$x][$y]['green'], $PixelMap[$x][$y]['blue'], $PixelMap[$x][$y]['alpha']); + ImageSetPixel($gdimg_dropshadow_temp, $x, $y, $thisColor); + } + } + } + + ImageSaveAlpha($gdimg, true); + ImageAlphaBlending($gdimg, false); + //$this->is_alpha = true; + $transparent2 = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0, 0, 0, 127); + ImageFilledRectangle($gdimg, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $transparent2); + ImageCopyResampled($gdimg, $gdimg_dropshadow_temp, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg_dropshadow_temp), ImageSY($gdimg_dropshadow_temp)); + + ImageDestroy($gdimg_dropshadow_temp); + } + return true; + } + + + function EdgeDetect(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EDGEDETECT)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::EdgeDetect($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Elipse($gdimg) { + if (phpthumb_functions::gd_version() < 2) { + return false; + } + // generate mask at twice desired resolution and downsample afterwards for easy antialiasing + if ($gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg) * 2, ImageSY($gdimg) * 2)) { + if ($gdimg_elipsemask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + + $color_transparent = ImageColorAllocate($gdimg_elipsemask_double, 255, 255, 255); + ImageFilledEllipse($gdimg_elipsemask_double, ImageSX($gdimg), ImageSY($gdimg), (ImageSX($gdimg) - 1) * 2, (ImageSY($gdimg) - 1) * 2, $color_transparent); + ImageCopyResampled($gdimg_elipsemask, $gdimg_elipsemask_double, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg), ImageSX($gdimg) * 2, ImageSY($gdimg) * 2); + + phpthumb_filters::ApplyMask($gdimg_elipsemask, $gdimg); + ImageDestroy($gdimg_elipsemask); + return true; + + } else { + $this->DebugMessage('$gdimg_elipsemask = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); + } + ImageDestroy($gdimg_elipsemask_double); + } else { + $this->DebugMessage('$gdimg_elipsemask_double = phpthumb_functions::ImageCreateFunction() failed', __FILE__, __LINE__); + } + return false; + } + + + function Emboss(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_EMBOSS)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_EMBOSS)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::Emboss($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Flip(&$gdimg, $x=false, $y=false) { + if (!$x && !$y) { + return false; + } + if ($tempImage = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + if ($x) { + ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + ImageCopy($gdimg, $tempImage, ImageSX($gdimg) - 1 - $x, 0, $x, 0, 1, ImageSY($gdimg)); + } + } + if ($y) { + ImageCopy($tempImage, $gdimg, 0, 0, 0, 0, ImageSX($gdimg), ImageSY($gdimg)); + for ($y = 0; $y < ImageSY($gdimg); $y++) { + ImageCopy($gdimg, $tempImage, 0, ImageSY($gdimg) - 1 - $y, 0, $y, ImageSX($gdimg), 1); + } + } + ImageDestroy($tempImage); + } + return true; + } + + + function Frame(&$gdimg, $frame_width, $edge_width, $hexcolor_frame, $hexcolor1, $hexcolor2) { + $frame_width = ($frame_width ? $frame_width : 5); + $edge_width = ($edge_width ? $edge_width : 1); + $hexcolor_frame = ($hexcolor_frame ? $hexcolor_frame : 'CCCCCC'); + $hexcolor1 = ($hexcolor1 ? $hexcolor1 : 'FFFFFF'); + $hexcolor2 = ($hexcolor2 ? $hexcolor2 : '000000'); + + $color_frame = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor_frame); + $color1 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor1); + $color2 = phpthumb_functions::ImageHexColorAllocate($gdimg, $hexcolor2); + for ($i = 0; $i < $edge_width; $i++) { + // outer bevel + ImageLine($gdimg, $i, $i, $i, ImageSY($gdimg) - $i, $color1); // left + ImageLine($gdimg, $i, $i, ImageSX($gdimg) - $i, $i, $color1); // top + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, ImageSX($gdimg) - $i, $i, $color2); // right + ImageLine($gdimg, ImageSX($gdimg) - $i, ImageSY($gdimg) - $i, $i, ImageSY($gdimg) - $i, $color2); // bottom + } + for ($i = 0; $i < $frame_width; $i++) { + // actual frame + ImageRectangle($gdimg, $edge_width + $i, $edge_width + $i, ImageSX($gdimg) - $edge_width - $i, ImageSY($gdimg) - $edge_width - $i, $color_frame); + } + for ($i = 0; $i < $edge_width; $i++) { + // inner bevel + ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color2); // left + ImageLine($gdimg, $frame_width + $edge_width + $i, $frame_width + $edge_width + $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color2); // top + ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, ImageSX($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, $color1); // right + ImageLine($gdimg, ImageSX($gdimg) - $frame_width - $edge_width - $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $frame_width + $edge_width + $i, ImageSY($gdimg) - $frame_width - $edge_width - $i, $color1); // bottom + } + return true; + } + + + function Gamma(&$gdimg, $amount) { + if (number_format($amount, 4) == '1.0000') { + return true; + } + return ImageGammaCorrect($gdimg, 1.0, $amount); + } + + + function Grayscale(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_GRAYSCALE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + return phpthumb_filters::Colorize($gdimg, 100, 'gray'); + } + + + function HistogramAnalysis(&$gdimg, $calculateGray=false) { + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + @$Analysis['red'][$OriginalPixel['red']]++; + @$Analysis['green'][$OriginalPixel['green']]++; + @$Analysis['blue'][$OriginalPixel['blue']]++; + @$Analysis['alpha'][$OriginalPixel['alpha']]++; + if ($calculateGray) { + $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + @$Analysis['gray'][$GrayPixel['red']]++; + } + } + } + $keys = array('red', 'green', 'blue', 'alpha'); + if ($calculateGray) { + $keys[] = 'gray'; + } + foreach ($keys as $dummy => $key) { + ksort($Analysis[$key]); + } + return $Analysis; + } + + + function HistogramStretch(&$gdimg, $band='*', $method=0, $threshold=0.1) { + // equivalent of "Auto Contrast" in Adobe Photoshop + // method 0 stretches according to RGB colors. Gives a more conservative stretch. + // method 1 band stretches according to grayscale which is color-biased (59% green, 30% red, 11% blue). May give a punchier / more aggressive stretch, possibly appearing over-saturated + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); + $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>(($method == 0) ? 'all' : 'gray')); + $band = substr($band, 0, 1); + if (!isset($keys[$band])) { + return false; + } + $key = $keys[$band]; + + // If the absolute brightest and darkest pixels are used then one random + // pixel in the image could throw off the whole system. Instead, count up/down + // from the limit and allow (default = 0.1%) of brightest/darkest + // pixels to be clipped to min/max + $threshold = floatval($threshold) / 100; + $clip_threshold = ImageSX($gdimg) * ImageSX($gdimg) * $threshold; + //if ($min >= 0) { + // $range_min = min($min, 255); + //} else { + $countsum = 0; + for ($i = 0; $i <= 255; $i++) { + if ($method == 0) { + $countsum = max(@$Analysis['red'][$i], @$Analysis['green'][$i], @$Analysis['blue'][$i]); + } else { + $countsum += @$Analysis[$key][$i]; + } + if ($countsum >= $clip_threshold) { + $range_min = $i - 1; + break; + } + } + $range_min = max($range_min, 0); + //} + //if ($max > 0) { + // $range_max = max($max, 255); + //} else { + $countsum = 0; + for ($i = 255; $i >= 0; $i--) { + if ($method == 0) { + $countsum = max(@$Analysis['red'][$i], @$Analysis['green'][$i], @$Analysis['blue'][$i]); + } else { + $countsum += @$Analysis[$key][$i]; + } + if ($countsum >= $clip_threshold) { + $range_max = $i + 1; + break; + } + } + $range_max = min($range_max, 255); + //} + $range_scale = (($range_max == $range_min) ? 1 : (255 / ($range_max - $range_min))); + if (($range_min == 0) && ($range_max == 255)) { + // no adjustment neccesary - don't waste CPU time! + return true; + } + + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + if ($band == '*') { + $new['red'] = min(255, max(0, ($OriginalPixel['red'] - $range_min) * $range_scale)); + $new['green'] = min(255, max(0, ($OriginalPixel['green'] - $range_min) * $range_scale)); + $new['blue'] = min(255, max(0, ($OriginalPixel['blue'] - $range_min) * $range_scale)); + $new['alpha'] = min(255, max(0, ($OriginalPixel['alpha'] - $range_min) * $range_scale)); + } else { + $new = $OriginalPixel; + $new[$key] = min(255, max(0, ($OriginalPixel[$key] - $range_min) * $range_scale)); + } + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $new['red'], $new['green'], $new['blue'], $new['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + + return true; + } + + + function HistogramOverlay(&$gdimg, $bands='*', $colors='', $width=0.25, $height=0.25, $alignment='BR', $opacity=50, $margin_x=5, $margin_y=null) { + $margin_y = (is_null($margin_y) ? $margin_x : $margin_y); + + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, true); + $histW = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); + $histH = round(($width > 1) ? min($width, ImageSX($gdimg)) : ImageSX($gdimg) * $width); + if ($gdHist = ImageCreateTrueColor($histW, $histH)) { + $color_back = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHist, 0, 0, 0, 127); + ImageFilledRectangle($gdHist, 0, 0, $histW, $histH, $color_back); + ImageAlphaBlending($gdHist, false); + ImageSaveAlpha($gdHist, true); + + $HistogramTempWidth = 256; + $HistogramTempHeight = 100; + if ($gdHistTemp = ImageCreateTrueColor($HistogramTempWidth, $HistogramTempHeight)) { + $color_back_temp = phpthumb_functions::ImageColorAllocateAlphaSafe($gdHistTemp, 255, 0, 255, 127); + ImageAlphaBlending($gdHistTemp, false); + ImageSaveAlpha($gdHistTemp, true); + ImageFilledRectangle($gdHistTemp, 0, 0, ImageSX($gdHistTemp), ImageSY($gdHistTemp), $color_back_temp); + + $DefaultColors = array('r'=>'FF0000', 'g'=>'00FF00', 'b'=>'0000FF', 'a'=>'999999', '*'=>'FFFFFF'); + $Colors = explode(';', $colors); + $BandsToGraph = array_unique(preg_split('//', $bands)); + $keys = array('r'=>'red', 'g'=>'green', 'b'=>'blue', 'a'=>'alpha', '*'=>'gray'); + foreach ($BandsToGraph as $key => $band) { + if (!isset($keys[$band])) { + continue; + } + $PeakValue = max($Analysis[$keys[$band]]); + $thisColor = phpthumb_functions::ImageHexColorAllocate($gdHistTemp, phpthumb_functions::IsHexColor(@$Colors[$key]) ? $Colors[$key] : $DefaultColors[$band]); + for ($x = 0; $x < $HistogramTempWidth; $x++) { + ImageLine($gdHistTemp, $x, $HistogramTempHeight - 1, $x, $HistogramTempHeight - 1 - round(@$Analysis[$keys[$band]][$x] / $PeakValue * $HistogramTempHeight), $thisColor); + } + ImageLine($gdHistTemp, 0, $HistogramTempHeight - 1, $HistogramTempWidth - 1, $HistogramTempHeight - 1, $thisColor); + ImageLine($gdHistTemp, 0, $HistogramTempHeight - 2, $HistogramTempWidth - 1, $HistogramTempHeight - 2, $thisColor); + } + ImageCopyResampled($gdHist, $gdHistTemp, 0, 0, 0, 0, ImageSX($gdHist), ImageSY($gdHist), ImageSX($gdHistTemp), ImageSY($gdHistTemp)); + ImageDestroy($gdHistTemp); + } else { + return false; + } + + phpthumb_filters::WatermarkOverlay($gdimg, $gdHist, $alignment, $opacity, $margin_x, $margin_y); + ImageDestroy($gdHist); + return true; + } + return false; + } + + + function ImageBorder(&$gdimg, $border_width, $radius_x, $radius_y, $hexcolor_border) { + $border_width = ($border_width ? $border_width : 1); + $radius_x = ($radius_x ? $radius_x : 0); + $radius_y = ($radius_y ? $radius_y : 0); + + $output_width = ImageSX($gdimg); + $output_height = ImageSY($gdimg); + + list($new_width, $new_height) = phpthumb_functions::ProportionalResize($output_width, $output_height, $output_width - max($border_width * 2, $radius_x), $output_height - max($border_width * 2, $radius_y)); + $offset_x = ($radius_x ? $output_width - $new_width - $radius_x : 0); + $offset_y = ($radius_y ? $output_height - $new_height - $radius_y : 0); + +//header('Content-Type: image/png'); +//ImagePNG($gdimg); +//exit; + if ($gd_border_canvas = phpthumb_functions::ImageCreateFunction($output_width, $output_height)) { + + ImageSaveAlpha($gd_border_canvas, true); + ImageAlphaBlending($gd_border_canvas, false); + $color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gd_border_canvas, 255, 255, 255, 127); + ImageFilledRectangle($gd_border_canvas, 0, 0, $output_width, $output_height, $color_background); + + $color_border = phpthumb_functions::ImageHexColorAllocate($gd_border_canvas, (phpthumb_functions::IsHexColor($hexcolor_border) ? $hexcolor_border : '000000')); + + for ($i = 0; $i < $border_width; $i++) { + ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $i, $output_width - $radius_x - ceil($offset_x / 2), $i, $color_border); // top + ImageLine($gd_border_canvas, floor($offset_x / 2) + $radius_x, $output_height - 1 - $i, $output_width - $radius_x - ceil($offset_x / 2), $output_height - 1 - $i, $color_border); // bottom + ImageLine($gd_border_canvas, floor($offset_x / 2) + $i, $radius_y, floor($offset_x / 2) + $i, $output_height - $radius_y, $color_border); // left + ImageLine($gd_border_canvas, $output_width - 1 - $i - ceil($offset_x / 2), $radius_y, $output_width - 1 - $i - ceil($offset_x / 2), $output_height - $radius_y, $color_border); // right + } + + if ($radius_x && $radius_y) { + + // PHP bug: ImageArc() with thicknesses > 1 give bad/undesirable/unpredicatable results + // Solution: Draw multiple 1px arcs side-by-side. + + // Problem: parallel arcs give strange/ugly antialiasing problems + // Solution: draw non-parallel arcs, from one side of the line thickness at the start angle + // to the opposite edge of the line thickness at the terminating angle + for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { + ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left + ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $thickness_offset - 1 + $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right + ImageArc($gd_border_canvas, $output_width - $radius_x - 1 - ceil($offset_x / 2), $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right + ImageArc($gd_border_canvas, floor($offset_x / 2) + 1 + $radius_x, $output_height - $thickness_offset - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left + } + if ($border_width > 1) { + for ($thickness_offset = 0; $thickness_offset < $border_width; $thickness_offset++) { + ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $radius_y, $radius_x * 2, $radius_y * 2, 180, 270, $color_border); // top-left + ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $radius_y, $radius_x * 2, $radius_y * 2, 270, 360, $color_border); // top-right + ImageArc($gd_border_canvas, $output_width - $thickness_offset - $radius_x - 1 - ceil($offset_x / 2), $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 0, 90, $color_border); // bottom-right + ImageArc($gd_border_canvas, floor($offset_x / 2) + $thickness_offset + $radius_x, $output_height - $radius_y, $radius_x * 2, $radius_y * 2, 90, 180, $color_border); // bottom-left + } + } + + } + $this->phpThumbObject->ImageResizeFunction($gd_border_canvas, $gdimg, floor(($output_width - $new_width) / 2), round(($output_height - $new_height) / 2), 0, 0, $new_width, $new_height, $output_width, $output_height); + + ImageDestroy($gdimg); + $gdimg = phpthumb_functions::ImageCreateFunction($output_width, $output_height); + ImageSaveAlpha($gdimg, true); + ImageAlphaBlending($gdimg, false); + $gdimg_color_background = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 255, 255, 255, 127); + ImageFilledRectangle($gdimg, 0, 0, $output_width, $output_height, $gdimg_color_background); + + ImageCopy($gdimg, $gd_border_canvas, 0, 0, 0, 0, $output_width, $output_height); + //$gdimg = $gd_border_canvas; + ImageDestroy($gd_border_canvas); + return true; + + + } else { + $this->DebugMessage('FAILED: $gd_border_canvas = phpthumb_functions::ImageCreateFunction('.$output_width.', '.$output_height.')', __FILE__, __LINE__); + } + return false; + } + + + function ImprovedImageRotate(&$gdimg_source, $rotate_angle=0, $config_background_hexcolor='FFFFFF', $bg=null) { + while ($rotate_angle < 0) { + $rotate_angle += 360; + } + $rotate_angle = $rotate_angle % 360; + if ($rotate_angle != 0) { + + $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_source, $config_background_hexcolor); + + if ((phpthumb_functions::gd_version() >= 2) && !$bg && ($rotate_angle % 90)) { + + //$this->DebugMessage('Using alpha rotate', __FILE__, __LINE__); + if ($gdimg_rotate_mask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_source), ImageSY($gdimg_source))) { + + for ($i = 0; $i <= 255; $i++) { + $color_mask[$i] = ImageColorAllocate($gdimg_rotate_mask, $i, $i, $i); + } + ImageFilledRectangle($gdimg_rotate_mask, 0, 0, ImageSX($gdimg_rotate_mask), ImageSY($gdimg_rotate_mask), $color_mask[255]); + $imageX = ImageSX($gdimg_source); + $imageY = ImageSY($gdimg_source); + for ($x = 0; $x < $imageX; $x++) { + for ($y = 0; $y < $imageY; $y++) { + $pixelcolor = phpthumb_functions::GetPixelColor($gdimg_source, $x, $y); + ImageSetPixel($gdimg_rotate_mask, $x, $y, $color_mask[255 - round($pixelcolor['alpha'] * 255 / 127)]); + } + } + $gdimg_rotate_mask = ImageRotate($gdimg_rotate_mask, $rotate_angle, $color_mask[0]); + $gdimg_source = ImageRotate($gdimg_source, $rotate_angle, $background_color); + + ImageAlphaBlending($gdimg_source, false); + ImageSaveAlpha($gdimg_source, true); + //$this->is_alpha = true; + $phpThumbFilters = new phpthumb_filters(); + $phpThumbFilters->phpThumbObject = $this; + $phpThumbFilters->ApplyMask($gdimg_rotate_mask, $gdimg_source); + + ImageDestroy($gdimg_rotate_mask); + + } else { + //$this->DebugMessage('ImageCreateFunction() failed', __FILE__, __LINE__); + } + + } else { + + if (phpthumb_functions::gd_version() < 2) { + //$this->DebugMessage('Using non-alpha rotate because gd_version is "'.phpthumb_functions::gd_version().'"', __FILE__, __LINE__); + } elseif ($bg) { + //$this->DebugMessage('Using non-alpha rotate because $this->bg is "'.$bg.'"', __FILE__, __LINE__); + } elseif ($rotate_angle % 90) { + //$this->DebugMessage('Using non-alpha rotate because ($rotate_angle % 90) = "'.($rotate_angle % 90).'"', __FILE__, __LINE__); + } else { + //$this->DebugMessage('Using non-alpha rotate because $this->thumbnailFormat is "'.$this->thumbnailFormat.'"', __FILE__, __LINE__); + } + + if (ImageColorTransparent($gdimg_source) >= 0) { + // ImageRotate() forgets all about an image's transparency and sets the transparent color to black + // To compensate, flood-fill the transparent color of the source image with the specified background color first + // then rotate and the colors should match + + if (!function_exists('ImageIsTrueColor') || !ImageIsTrueColor($gdimg_source)) { + // convert paletted image to true-color before rotating to prevent nasty aliasing artifacts + + //$this->source_width = ImageSX($gdimg_source); + //$this->source_height = ImageSY($gdimg_source); + $gdimg_newsrc = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg_source), ImageSY($gdimg_source)); + $background_color = phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $config_background_hexcolor); + ImageFilledRectangle($gdimg_newsrc, 0, 0, ImageSX($gdimg_source), ImageSY($gdimg_source), phpthumb_functions::ImageHexColorAllocate($gdimg_newsrc, $config_background_hexcolor)); + ImageCopy($gdimg_newsrc, $gdimg_source, 0, 0, 0, 0, ImageSX($gdimg_source), ImageSY($gdimg_source)); + ImageDestroy($gdimg_source); + unset($gdimg_source); + $gdimg_source = $gdimg_newsrc; + unset($gdimg_newsrc); + + } else { + + ImageColorSet( + $gdimg_source, + ImageColorTransparent($gdimg_source), + hexdec(substr($config_background_hexcolor, 0, 2)), + hexdec(substr($config_background_hexcolor, 2, 2)), + hexdec(substr($config_background_hexcolor, 4, 2))); + + ImageColorTransparent($gdimg_source, -1); + + } + } + + $gdimg_source = ImageRotate($gdimg_source, $rotate_angle, $background_color); + + } + } + return true; + } + + + function MeanRemoval(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_MEAN_REMOVAL)', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::MeanRemoval($gdimg) [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Negative(&$gdimg) { + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_NEGATE)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_NEGATE)', __FILE__, __LINE__); + // fall through and try it the hard way + } + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, (~$currentPixel['red'] & 0xFF), (~$currentPixel['green'] & 0xFF), (~$currentPixel['blue'] & 0xFF), $currentPixel['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function RoundedImageCorners(&$gdimg, $radius_x, $radius_y) { + // generate mask at twice desired resolution and downsample afterwards for easy antialiasing + // mask is generated as a white double-size elipse on a triple-size black background and copy-paste-resampled + // onto a correct-size mask image as 4 corners due to errors when the entire mask is resampled at once (gray edges) + if ($gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction($radius_x * 6, $radius_y * 6)) { + if ($gdimg_cornermask = phpthumb_functions::ImageCreateFunction(ImageSX($gdimg), ImageSY($gdimg))) { + + $color_transparent = ImageColorAllocate($gdimg_cornermask_triple, 255, 255, 255); + ImageFilledEllipse($gdimg_cornermask_triple, $radius_x * 3, $radius_y * 3, $radius_x * 4, $radius_y * 4, $color_transparent); + + ImageFilledRectangle($gdimg_cornermask, 0, 0, ImageSX($gdimg), ImageSY($gdimg), $color_transparent); + + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, 0, $radius_x, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, 0, ImageSY($gdimg) - $radius_y, $radius_x, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, ImageSY($gdimg) - $radius_y, $radius_x * 3, $radius_y * 3, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + ImageCopyResampled($gdimg_cornermask, $gdimg_cornermask_triple, ImageSX($gdimg) - $radius_x, 0, $radius_x * 3, $radius_y, $radius_x, $radius_y, $radius_x * 2, $radius_y * 2); + + phpthumb_filters::ApplyMask($gdimg_cornermask, $gdimg); + ImageDestroy($gdimg_cornermask); + $this->DebugMessage('RoundedImageCorners('.$radius_x.', '.$radius_y.') succeeded', __FILE__, __LINE__); + return true; + + } else { + $this->DebugMessage('FAILED: $gdimg_cornermask = phpthumb_functions::ImageCreateFunction('.ImageSX($gdimg).', '.ImageSY($gdimg).')', __FILE__, __LINE__); + } + ImageDestroy($gdimg_cornermask_triple); + + } else { + $this->DebugMessage('FAILED: $gdimg_cornermask_triple = phpthumb_functions::ImageCreateFunction('.($radius_x * 6).', '.($radius_y * 6).')', __FILE__, __LINE__); + } + return false; + } + + + function Saturation(&$gdimg, $amount, $color='') { + if ($amount == 0) { + return true; + } elseif ($amount > 0) { + $amount = 0 - $amount; + } else { + $amount = abs($amount); + } + return phpthumb_filters::Desaturate($gdimg, $amount, $color); + } + + + function Sepia(&$gdimg, $amount, $targetColor) { + $amount = (is_numeric($amount) ? max(0, min(100, $amount)) : 50); + $targetColor = (phpthumb_functions::IsHexColor($targetColor) ? $targetColor : 'A28065'); + + if ($amount == 0) { + return true; + } + + $TargetPixel['red'] = hexdec(substr($targetColor, 0, 2)); + $TargetPixel['green'] = hexdec(substr($targetColor, 2, 2)); + $TargetPixel['blue'] = hexdec(substr($targetColor, 4, 2)); + + $ImageSX = ImageSX($gdimg); + $ImageSY = ImageSY($gdimg); + for ($x = 0; $x < $ImageSX; $x++) { + for ($y = 0; $y < $ImageSY; $y++) { + $OriginalPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $GrayPixel = phpthumb_functions::GrayscalePixel($OriginalPixel); + + // http://www.gimpguru.org/Tutorials/SepiaToning/ + // "In the traditional sepia toning process, the tinting occurs most in + // the mid-tones: the lighter and darker areas appear to be closer to B&W." + $SepiaAmount = ((128 - abs($GrayPixel['red'] - 128)) / 128) * ($amount / 100); + + foreach ($TargetPixel as $key => $value) { + $NewPixel[$key] = round(max(0, min(255, $GrayPixel[$key] * (1 - $SepiaAmount) + ($TargetPixel[$key] * $SepiaAmount)))); + } + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, $NewPixel['red'], $NewPixel['green'], $NewPixel['blue'], $OriginalPixel['alpha']); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function Smooth(&$gdimg, $amount=6) { + $amount = min(25, max(0, $amount)); + if ($amount == 0) { + return true; + } + if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) { + if (ImageFilter($gdimg, IMG_FILTER_SMOOTH, $amount)) { + return true; + } + $this->DebugMessage('FAILED: ImageFilter($gdimg, IMG_FILTER_SMOOTH, '.$amount.')', __FILE__, __LINE__); + // fall through and try it the hard way + } + // currently not implemented "the hard way" + $this->DebugMessage('FAILED: phpthumb_filters::Smooth($gdimg, '.$amount.') [function not implemented]', __FILE__, __LINE__); + return false; + } + + + function Threshold(&$gdimg, $cutoff) { + $cutoff = min(255, max(0, ($cutoff ? $cutoff : 128))); + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $grayPixel = phpthumb_functions::GrayscalePixel($currentPixel); + if ($grayPixel['red'] < $cutoff) { + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0x00, 0x00, 0x00, $currentPixel['alpha']); + } else { + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg, 0xFF, 0xFF, 0xFF, $currentPixel['alpha']); + } + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function ImageTrueColorToPalette2(&$image, $dither, $ncolors) { + // http://www.php.net/manual/en/function.imagetruecolortopalette.php + // zmorris at zsculpt dot com (17-Aug-2004 06:58) + $width = ImageSX($image); + $height = ImageSY($image); + $image_copy = ImageCreateTrueColor($width, $height); + //ImageCopyMerge($image_copy, $image, 0, 0, 0, 0, $width, $height, 100); + ImageCopy($image_copy, $image, 0, 0, 0, 0, $width, $height); + ImageTrueColorToPalette($image, $dither, $ncolors); + ImageColorMatch($image_copy, $image); + ImageDestroy($image_copy); + return true; + } + + function ReduceColorDepth(&$gdimg, $colors=256, $dither=true) { + $colors = max(min($colors, 256), 2); + // ImageTrueColorToPalette usually makes ugly colors, the replacement is a bit better + //ImageTrueColorToPalette($gdimg, $dither, $colors); + phpthumb_filters::ImageTrueColorToPalette2($gdimg, $dither, $colors); + return true; + } + + + function WhiteBalance(&$gdimg, $targetColor='') { + if (phpthumb_functions::IsHexColor($targetColor)) { + $targetPixel = array( + 'red' => hexdec(substr($targetColor, 0, 2)), + 'green' => hexdec(substr($targetColor, 2, 2)), + 'blue' => hexdec(substr($targetColor, 4, 2)) + ); + } else { + $Analysis = phpthumb_filters::HistogramAnalysis($gdimg, false); + $targetPixel = array( + 'red' => max(array_keys($Analysis['red'])), + 'green' => max(array_keys($Analysis['green'])), + 'blue' => max(array_keys($Analysis['blue'])) + ); + } + $grayValue = phpthumb_functions::GrayscaleValue($targetPixel['red'], $targetPixel['green'], $targetPixel['blue']); + $scaleR = $grayValue / $targetPixel['red']; + $scaleG = $grayValue / $targetPixel['green']; + $scaleB = $grayValue / $targetPixel['blue']; + + for ($x = 0; $x < ImageSX($gdimg); $x++) { + for ($y = 0; $y < ImageSY($gdimg); $y++) { + $currentPixel = phpthumb_functions::GetPixelColor($gdimg, $x, $y); + $newColor = phpthumb_functions::ImageColorAllocateAlphaSafe( + $gdimg, + max(0, min(255, round($currentPixel['red'] * $scaleR))), + max(0, min(255, round($currentPixel['green'] * $scaleG))), + max(0, min(255, round($currentPixel['blue'] * $scaleB))), + $currentPixel['alpha'] + ); + ImageSetPixel($gdimg, $x, $y, $newColor); + } + } + return true; + } + + + function WatermarkText(&$gdimg, $text, $size, $alignment, $hex_color='000000', $ttffont='', $opacity=100, $margin=5, $angle=0, $bg_color=false, $bg_opacity=0, $fillextend='') { + // text watermark requested + if (!$text) { + return false; + } + ImageAlphaBlending($gdimg, true); + + $metaTextArray = array( + '^Fb' => $this->phpThumbObject->getimagesizeinfo['filesize'], + '^Fk' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1024), + '^Fm' => round($this->phpThumbObject->getimagesizeinfo['filesize'] / 1048576), + '^X' => $this->phpThumbObject->getimagesizeinfo[0], + '^Y' => $this->phpThumbObject->getimagesizeinfo[1], + '^x' => ImageSX($gdimg), + '^y' => ImageSY($gdimg), + '^^' => '^', + ); + $text = strtr($text, $metaTextArray); + + $text = str_replace("\r\n", "\n", $text); + $text = str_replace("\r", "\n", $text); + $textlines = explode("\n", $text); + + if (@is_readable($ttffont) && is_file($ttffont)) { + + $opacity = 100 - intval(max(min($opacity, 100), 0)); + + $this->DebugMessage('Using TTF font "'.$ttffont.'"', __FILE__, __LINE__); + + $TTFbox = ImageTTFbBox($size, $angle, $ttffont, $text); + + $min_x = min($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); + $max_x = max($TTFbox[0], $TTFbox[2], $TTFbox[4], $TTFbox[6]); + //$text_width = round($max_x - $min_x + ($size * 0.5)); + $text_width = round($max_x - $min_x); + + $min_y = min($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); + $max_y = max($TTFbox[1], $TTFbox[3], $TTFbox[5], $TTFbox[7]); + //$text_height = round($max_y - $min_y + ($size * 0.5)); + $text_height = round($max_y - $min_y); + + $TTFboxChar = ImageTTFbBox($size, $angle, $ttffont, 'jH'); + $char_min_y = min($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); + $char_max_y = max($TTFboxChar[1], $TTFboxChar[3], $TTFboxChar[5], $TTFboxChar[7]); + $char_height = round($char_max_y - $char_min_y); + + switch ($alignment) { + case 'T': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = $char_height + $margin; + break; + + case 'B': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + + case 'L': + $text_origin_x = $margin; + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'R': + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'C': + $text_origin_x = round((ImageSX($gdimg) - $text_width) / 2); + $text_origin_y = round((ImageSY($gdimg) - $text_height) / 2) + $char_height; + break; + + case 'TL': + $text_origin_x = $margin; + $text_origin_y = $char_height + $margin; + break; + + case 'TR': + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = $char_height + $margin; + break; + + case 'BL': + $text_origin_x = $margin; + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + + case 'BR': + default: + $text_origin_x = ImageSX($gdimg) - $text_width + $TTFbox[0] - $min_x + round($size * 0.25) - $margin; + $text_origin_y = ImageSY($gdimg) + $TTFbox[1] - $margin; + break; + } + $letter_color_text = phpthumb_functions::ImageHexColorAllocate($gdimg, $hex_color, false, $opacity * 1.27); + + if ($alignment == '*') { + + $text_origin_y = $char_height + $margin; + while (($text_origin_y - $text_height) < ImageSY($gdimg)) { + $text_origin_x = $margin; + while ($text_origin_x < ImageSX($gdimg)) { + ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); + $text_origin_x += ($text_width + $margin); + } + $text_origin_y += ($text_height + $margin); + } + + } else { + + //ImageRectangle($gdimg, $text_origin_x + $min_x, $text_origin_y + $TTFbox[1], $text_origin_x + $min_x + $text_width, $text_origin_y + $TTFbox[1] - $text_height, $letter_color_text); + if (phpthumb_functions::IsHexColor($bg_color)) { + $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); + $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, $bg_color, false, $text_background_alpha); + } else { + $text_color_background = phpthumb_functions::ImageHexColorAllocate($gdimg, 'FFFFFF', false, 127); + } + $x1 = $text_origin_x + $min_x; + $y1 = $text_origin_y + $TTFbox[1]; + $x2 = $text_origin_x + $min_x + $text_width; + $y2 = $text_origin_y + $TTFbox[1] - $text_height; + $x_TL = eregi('x', $fillextend) ? 0 : min($x1, $x2); + $y_TL = eregi('y', $fillextend) ? 0 : min($y1, $y2); + $x_BR = eregi('x', $fillextend) ? ImageSX($gdimg) : max($x1, $x2); + $y_BR = eregi('y', $fillextend) ? ImageSY($gdimg) : max($y1, $y2); + //while ($y_BR > ImageSY($gdimg)) { + // $y_TL--; + // $y_BR--; + // $text_origin_y--; + //} + ImageFilledRectangle($gdimg, $x_TL, $y_TL, $x_BR, $y_BR, $text_color_background); + ImageTTFtext($gdimg, $size, $angle, $text_origin_x, $text_origin_y, $letter_color_text, $ttffont, $text); + + } + return true; + + } else { + + $size = min(5, max(1, $size)); + $this->DebugMessage('Using built-in font (size='.$size.') for text watermark'.($ttffont ? ' because $ttffont !is_readable('.$ttffont.')' : ''), __FILE__, __LINE__); + + $text_width = 0; + $text_height = 0; + foreach ($textlines as $dummy => $line) { + $text_width = max($text_width, ImageFontWidth($size) * strlen($line)); + $text_height += ImageFontHeight($size); + } + if ($img_watermark = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { + ImageAlphaBlending($img_watermark, false); + if (phpthumb_functions::IsHexColor($bg_color)) { + $text_background_alpha = round(127 * ((100 - min(max(0, $bg_opacity), 100)) / 100)); + $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, $bg_color, false, $text_background_alpha); + } else { + $text_color_background = phpthumb_functions::ImageHexColorAllocate($img_watermark, 'FFFFFF', false, 127); + } + ImageFilledRectangle($img_watermark, 0, 0, ImageSX($img_watermark), ImageSY($img_watermark), $text_color_background); + + if ($angle && function_exists('ImageRotate')) { + // using $img_watermark_mask is pointless if ImageRotate function isn't available + if ($img_watermark_mask = phpthumb_functions::ImageCreateFunction($text_width, $text_height)) { + $mask_color_background = ImageColorAllocate($img_watermark_mask, 0, 0, 0); + ImageAlphaBlending($img_watermark_mask, false); + ImageFilledRectangle($img_watermark_mask, 0, 0, ImageSX($img_watermark_mask), ImageSY($img_watermark_mask), $mask_color_background); + $mask_color_watermark = ImageColorAllocate($img_watermark_mask, 255, 255, 255); + } + } + + $text_color_watermark = phpthumb_functions::ImageHexColorAllocate($img_watermark, $hex_color); + foreach ($textlines as $key => $line) { + switch ($alignment) { + case 'C': + case 'T': + case 'B': + $x_offset = round(($text_width - (ImageFontWidth($size) * strlen($line))) / 2); + break; + + case 'L': + case 'TL': + case 'BL': + $x_offset = 0; + break; + + case 'R': + case 'TR': + case 'BR': + default: + $x_offset = $text_width - (ImageFontWidth($size) * strlen($line)); + break; + } + ImageString($img_watermark, $size, $x_offset, $key * ImageFontHeight($size), $line, $text_color_watermark); + if ($angle && $img_watermark_mask) { + ImageString($img_watermark_mask, $size, $x_offset, $key * ImageFontHeight($size), $text, $mask_color_watermark); + } + } + if ($angle && $img_watermark_mask) { + $img_watermark = ImageRotate($img_watermark, $angle, $text_color_background); + $img_watermark_mask = ImageRotate($img_watermark_mask, $angle, $mask_color_background); + phpthumb_filters::ApplyMask($img_watermark_mask, $img_watermark); + } + phpthumb_filters::WatermarkOverlay($gdimg, $img_watermark, $alignment, $opacity, $margin); + ImageDestroy($img_watermark); + return true; + } + + } + return false; + } + + + function WatermarkOverlay(&$gdimg_dest, &$img_watermark, $alignment='*', $opacity=50, $margin_x=5, $margin_y=null) { + if (is_resource($gdimg_dest) && is_resource($img_watermark)) { + $watermark_source_x = 0; + $watermark_source_y = 0; + $img_source_width = ImageSX($gdimg_dest); + $img_source_height = ImageSY($gdimg_dest); + $watermark_source_width = ImageSX($img_watermark); + $watermark_source_height = ImageSY($img_watermark); + $watermark_opacity_percent = max(0, min(100, $opacity)); + $margin_y = (is_null($margin_y) ? $margin_x : $margin_y); + $watermark_margin_x = ((($margin_x > 0) && ($margin_x < 1)) ? round((1 - $margin_x) * $img_source_width) : $margin_x); + $watermark_margin_y = ((($margin_y > 0) && ($margin_y < 1)) ? round((1 - $margin_y) * $img_source_height) : $margin_y); + switch ($alignment) { + case '*': + if ($gdimg_tiledwatermark = phpthumb_functions::ImageCreateFunction($img_source_width, $img_source_height)) { + + ImageAlphaBlending($gdimg_tiledwatermark, false); + ImageSaveAlpha($gdimg_tiledwatermark, true); + $text_color_transparent = phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_tiledwatermark, 255, 0, 255, 127); + ImageFill($gdimg_tiledwatermark, 0, 0, $text_color_transparent); + + // set the tiled image transparent color to whatever the untiled image transparency index is +// ImageColorTransparent($gdimg_tiledwatermark, ImageColorTransparent($img_watermark)); + + // a "cleaner" way of doing it, but can't handle the margin feature :( +// ImageSetTile($gdimg_tiledwatermark, $img_watermark); +// ImageFill($gdimg_tiledwatermark, 0, 0, IMG_COLOR_TILED); +// break; + +// ImageFill($gdimg_tiledwatermark, 0, 0, ImageColorTransparent($gdimg_tiledwatermark)); + // tile the image as many times as can fit + for ($x = $watermark_margin_x; $x < ($img_source_width + $watermark_source_width); $x += ($watermark_source_width + $watermark_margin_x)) { + for ($y = $watermark_margin_y; $y < ($img_source_height + $watermark_source_height); $y += ($watermark_source_height + $watermark_margin_y)) { + ImageCopy( + $gdimg_tiledwatermark, + $img_watermark, + $x, + $y, + 0, + 0, + min($watermark_source_width, $img_source_width - $x - $watermark_margin_x), + min($watermark_source_height, $img_source_height - $y - $watermark_margin_y) + ); + } + } + + $watermark_source_width = ImageSX($gdimg_tiledwatermark); + $watermark_source_height = ImageSY($gdimg_tiledwatermark); + $watermark_destination_x = 0; + $watermark_destination_y = 0; + + ImageDestroy($img_watermark); + $img_watermark = $gdimg_tiledwatermark; + } + break; + + case 'T': + $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); + $watermark_destination_y = $watermark_margin_y; + break; + + case 'B': + $watermark_destination_x = round((($img_source_width / 2) - ($watermark_source_width / 2)) + $watermark_margin_x); + $watermark_destination_y = $img_source_height - $watermark_source_height - $watermark_margin_y; + break; + + case 'L': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); + break; + + case 'R': + $watermark_destination_x = $img_source_width - $watermark_source_width - $watermark_margin_x; + $watermark_destination_y = round((($img_source_height / 2) - ($watermark_source_height / 2)) + $watermark_margin_y); + break; + + case 'C': + $watermark_destination_x = round(($img_source_width / 2) - ($watermark_source_width / 2)); + $watermark_destination_y = round(($img_source_height / 2) - ($watermark_source_height / 2)); + break; + + case 'TL': + $watermark_destination_x = $watermark_margin_x; + $watermark_destination_y = $watermark_margin_y; + break; + + case 'TR': + $watermark_destination_x = $img_source_width - $watermark_source_width - $watermark_margin_x; + $watermark_destination_y = $watermark_margin_y; + break; + + case 'BL': +//echo '
    ';
    +////var_dump($watermark_destination_x);
    +////var_dump($watermark_destination_y);
    +//var_dump($watermark_margin_x);
    +//var_dump($img_source_height);
    +//var_dump($watermark_source_height);
    +//var_dump($watermark_margin_y);
    +					$watermark_destination_x = $watermark_margin_x;
    +					$watermark_destination_y = $img_source_height - $watermark_source_height - $watermark_margin_y;
    +					break;
    +
    +				case 'BR':
    +				default:
    +					$watermark_destination_x = $img_source_width  - $watermark_source_width  - $watermark_margin_x;
    +					$watermark_destination_y = $img_source_height - $watermark_source_height - $watermark_margin_y;
    +					break;
    +			}
    +			ImageAlphaBlending($gdimg_dest, false);
    +			ImageSaveAlpha($gdimg_dest, true);
    +			ImageSaveAlpha($img_watermark, true);
    +			phpthumb_functions::ImageCopyRespectAlpha($gdimg_dest, $img_watermark, $watermark_destination_x, $watermark_destination_y, 0, 0, $watermark_source_width, $watermark_source_height, $watermark_opacity_percent);
    +
    +			return true;
    +		}
    +		return false;
    +	}
    +
    +
    +	function DebugMessage($message, $file='', $line='') {
    +		if (is_object($this->phpThumbObject)) {
    +			return $this->phpThumbObject->DebugMessage($message, $file, $line);
    +		}
    +		return false;
    +	}
    +}
    +
    +?>
    \ No newline at end of file
    diff --git a/common/phpThumb/phpthumb.functions.php b/common/phpThumb/phpthumb.functions.php
    new file mode 100644
    index 0000000..8846dfa
    --- /dev/null
    +++ b/common/phpThumb/phpthumb.functions.php
    @@ -0,0 +1,963 @@
    +   //
    +//        available at http://phpthumb.sourceforge.net     ///
    +//////////////////////////////////////////////////////////////
    +///                                                         //
    +// phpthumb.functions.php - general support functions       //
    +//                                                         ///
    +//////////////////////////////////////////////////////////////
    +
    +class phpthumb_functions {
    +
    +	function user_function_exists($functionname) {
    +		if (function_exists('get_defined_functions')) {
    +			static $get_defined_functions = array();
    +			if (empty($get_defined_functions)) {
    +				$get_defined_functions = get_defined_functions();
    +			}
    +			return in_array(strtolower($functionname), $get_defined_functions['user']);
    +		}
    +		return function_exists($functionname);
    +	}
    +
    +
    +	function builtin_function_exists($functionname) {
    +		if (function_exists('get_defined_functions')) {
    +			static $get_defined_functions = array();
    +			if (empty($get_defined_functions)) {
    +				$get_defined_functions = get_defined_functions();
    +			}
    +			return in_array(strtolower($functionname), $get_defined_functions['internal']);
    +		}
    +		return function_exists($functionname);
    +	}
    +
    +
    +	function version_compare_replacement_sub($version1, $version2, $operator='') {
    +		// If you specify the third optional operator argument, you can test for a particular relationship.
    +		// The possible operators are: <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne respectively.
    +		// Using this argument, the function will return 1 if the relationship is the one specified by the operator, 0 otherwise.
    +
    +		// If a part contains special version strings these are handled in the following order: dev < (alpha = a) < (beta = b) < RC < pl
    +		static $versiontype_lookup = array();
    +		if (empty($versiontype_lookup)) {
    +			$versiontype_lookup['dev']   = 10001;
    +			$versiontype_lookup['a']     = 10002;
    +			$versiontype_lookup['alpha'] = 10002;
    +			$versiontype_lookup['b']     = 10003;
    +			$versiontype_lookup['beta']  = 10003;
    +			$versiontype_lookup['RC']    = 10004;
    +			$versiontype_lookup['pl']    = 10005;
    +		}
    +		if (isset($versiontype_lookup[$version1])) {
    +			$version1 = $versiontype_lookup[$version1];
    +		}
    +		if (isset($versiontype_lookup[$version2])) {
    +			$version2 = $versiontype_lookup[$version2];
    +		}
    +
    +		switch ($operator) {
    +			case '<':
    +			case 'lt':
    +				return intval($version1 < $version2);
    +				break;
    +			case '<=':
    +			case 'le':
    +				return intval($version1 <= $version2);
    +				break;
    +			case '>':
    +			case 'gt':
    +				return intval($version1 > $version2);
    +				break;
    +			case '>=':
    +			case 'ge':
    +				return intval($version1 >= $version2);
    +				break;
    +			case '==':
    +			case '=':
    +			case 'eq':
    +				return intval($version1 == $version2);
    +				break;
    +			case '!=':
    +			case '<>':
    +			case 'ne':
    +				return intval($version1 != $version2);
    +				break;
    +		}
    +		if ($version1 == $version2) {
    +			return 0;
    +		} elseif ($version1 < $version2) {
    +			return -1;
    +		}
    +		return 1;
    +	}
    +
    +
    +	function version_compare_replacement($version1, $version2, $operator='') {
    +		if (function_exists('version_compare')) {
    +			// built into PHP v4.1.0+
    +			return version_compare($version1, $version2, $operator);
    +		}
    +
    +		// The function first replaces _, - and + with a dot . in the version strings
    +		$version1 = strtr($version1, '_-+', '...');
    +		$version2 = strtr($version2, '_-+', '...');
    +
    +		// and also inserts dots . before and after any non number so that for example '4.3.2RC1' becomes '4.3.2.RC.1'.
    +		// Then it splits the results like if you were using explode('.',$ver). Then it compares the parts starting from left to right.
    +		$version1 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version1);
    +		$version2 = eregi_replace('([0-9]+)([A-Z]+)([0-9]+)', '\\1.\\2.\\3', $version2);
    +
    +		$parts1 = explode('.', $version1);
    +		$parts2 = explode('.', $version1);
    +		$parts_count = max(count($parts1), count($parts2));
    +		for ($i = 0; $i < $parts_count; $i++) {
    +			$comparison = phpthumb_functions::version_compare_replacement_sub($version1, $version2, $operator);
    +			if ($comparison != 0) {
    +				return $comparison;
    +			}
    +		}
    +		return 0;
    +	}
    +
    +
    +	function phpinfo_array() {
    +		static $phpinfo_array = array();
    +		if (empty($phpinfo_array)) {
    +			ob_start();
    +			phpinfo();
    +			$phpinfo = ob_get_contents();
    +			ob_end_clean();
    +			$phpinfo_array = explode("\n", $phpinfo);
    +		}
    +		return $phpinfo_array;
    +	}
    +
    +
    +	function exif_info() {
    +		static $exif_info = array();
    +		if (empty($exif_info)) {
    +			// based on code by johnschaefer at gmx dot de
    +			// from PHP help on gd_info()
    +			$exif_info = array(
    +				'EXIF Support'           => '',
    +				'EXIF Version'           => '',
    +				'Supported EXIF Version' => '',
    +				'Supported filetypes'    => ''
    +			);
    +			$phpinfo_array = phpthumb_functions::phpinfo_array();
    +			foreach ($phpinfo_array as $line) {
    +				$line = trim(strip_tags($line));
    +				foreach ($exif_info as $key => $value) {
    +					if (strpos($line, $key) === 0) {
    +						$newvalue = trim(str_replace($key, '', $line));
    +						$exif_info[$key] = $newvalue;
    +					}
    +				}
    +			}
    +		}
    +		return $exif_info;
    +	}
    +
    +
    +	function ImageTypeToMIMEtype($imagetype) {
    +		if (function_exists('image_type_to_mime_type') && ($imagetype >= 1) && ($imagetype <= 16)) {
    +			// PHP v4.3.0+
    +			return image_type_to_mime_type($imagetype);
    +		}
    +		static $image_type_to_mime_type = array(
    +			1  => 'image/gif',                     // IMAGETYPE_GIF
    +			2  => 'image/jpeg',                    // IMAGETYPE_JPEG
    +			3  => 'image/png',                     // IMAGETYPE_PNG
    +			4  => 'application/x-shockwave-flash', // IMAGETYPE_SWF
    +			5  => 'image/psd',                     // IMAGETYPE_PSD
    +			6  => 'image/bmp',                     // IMAGETYPE_BMP
    +			7  => 'image/tiff',                    // IMAGETYPE_TIFF_II (intel byte order)
    +			8  => 'image/tiff',                    // IMAGETYPE_TIFF_MM (motorola byte order)
    +			9  => 'application/octet-stream',      // IMAGETYPE_JPC
    +			10 => 'image/jp2',                     // IMAGETYPE_JP2
    +			11 => 'application/octet-stream',      // IMAGETYPE_JPX
    +			12 => 'application/octet-stream',      // IMAGETYPE_JB2
    +			13 => 'application/x-shockwave-flash', // IMAGETYPE_SWC
    +			14 => 'image/iff',                     // IMAGETYPE_IFF
    +			15 => 'image/vnd.wap.wbmp',            // IMAGETYPE_WBMP
    +			16 => 'image/xbm',                     // IMAGETYPE_XBM
    +
    +			'gif'  => 'image/gif',                 // IMAGETYPE_GIF
    +			'jpg'  => 'image/jpeg',                // IMAGETYPE_JPEG
    +			'jpeg' => 'image/jpeg',                // IMAGETYPE_JPEG
    +			'png'  => 'image/png',                 // IMAGETYPE_PNG
    +			'bmp'  => 'image/bmp',                 // IMAGETYPE_BMP
    +			'ico'  => 'image/x-icon',
    +		);
    +
    +		return (isset($image_type_to_mime_type[$imagetype]) ? $image_type_to_mime_type[$imagetype] : false);
    +	}
    +
    +
    +	function HexCharDisplay($string) {
    +		$len = strlen($string);
    +		$output = '';
    +		for ($i = 0; $i < $len; $i++) {
    +			$output .= ' 0x'.str_pad(dechex(ord($string{$i})), 2, '0', STR_PAD_LEFT);
    +		}
    +		return $output;
    +	}
    +
    +
    +	function IsHexColor($HexColorString) {
    +		return eregi('^[0-9A-F]{6}$', $HexColorString);
    +	}
    +
    +
    +	function ImageColorAllocateAlphaSafe(&$gdimg_hexcolorallocate, $R, $G, $B, $alpha=false) {
    +		if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.2', '>=') && ($alpha !== false)) {
    +			return ImageColorAllocateAlpha($gdimg_hexcolorallocate, $R, $G, $B, intval($alpha));
    +		} else {
    +			return ImageColorAllocate($gdimg_hexcolorallocate, $R, $G, $B);
    +		}
    +	}
    +
    +	function ImageHexColorAllocate(&$gdimg_hexcolorallocate, $HexColorString, $dieOnInvalid=false, $alpha=false) {
    +		if (!is_resource($gdimg_hexcolorallocate)) {
    +			die('$gdimg_hexcolorallocate is not a GD resource in ImageHexColorAllocate()');
    +		}
    +		if (phpthumb_functions::IsHexColor($HexColorString)) {
    +			$R = hexdec(substr($HexColorString, 0, 2));
    +			$G = hexdec(substr($HexColorString, 2, 2));
    +			$B = hexdec(substr($HexColorString, 4, 2));
    +			return phpthumb_functions::ImageColorAllocateAlphaSafe($gdimg_hexcolorallocate, $R, $G, $B, $alpha);
    +		}
    +		if ($dieOnInvalid) {
    +			die('Invalid hex color string: "'.$HexColorString.'"');
    +		}
    +		return ImageColorAllocate($gdimg_hexcolorallocate, 0x00, 0x00, 0x00);
    +	}
    +
    +
    +	function HexColorXOR($hexcolor) {
    +		return strtoupper(str_pad(dechex(~hexdec($hexcolor) & 0xFFFFFF), 6, '0', STR_PAD_LEFT));
    +	}
    +
    +
    +	function GetPixelColor(&$img, $x, $y) {
    +		if (!is_resource($img)) {
    +			return false;
    +		}
    +		return @ImageColorsForIndex($img, @ImageColorAt($img, $x, $y));
    +	}
    +
    +
    +	function GrayscaleValue($r, $g, $b) {
    +		return round(($r * 0.30) + ($g * 0.59) + ($b * 0.11));
    +	}
    +
    +
    +	function GrayscalePixel($OriginalPixel) {
    +		$gray = phpthumb_functions::GrayscaleValue($OriginalPixel['red'], $OriginalPixel['green'], $OriginalPixel['blue']);
    +		return array('red'=>$gray, 'green'=>$gray, 'blue'=>$gray);
    +	}
    +
    +
    +	function GrayscalePixelRGB($rgb) {
    +		$r = ($rgb >> 16) & 0xFF;
    +		$g = ($rgb >>  8) & 0xFF;
    +		$b =  $rgb        & 0xFF;
    +		return ($r * 0.299) + ($g * 0.587) + ($b * 0.114);
    +	}
    +
    +
    +	function ImageCopyResampleBicubic($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) {
    +		// ron at korving dot demon dot nl
    +		// http://www.php.net/imagecopyresampled
    +
    +		$scaleX = ($src_w - 1) / $dst_w;
    +		$scaleY = ($src_h - 1) / $dst_h;
    +
    +		$scaleX2 = $scaleX / 2.0;
    +		$scaleY2 = $scaleY / 2.0;
    +
    +		$isTrueColor = ImageIsTrueColor($src_img);
    +
    +		for ($y = $src_y; $y < $src_y + $dst_h; $y++) {
    +			$sY   = $y * $scaleY;
    +			$siY  = (int) $sY;
    +			$siY2 = (int) $sY + $scaleY2;
    +
    +			for ($x = $src_x; $x < $src_x + $dst_w; $x++) {
    +				$sX   = $x * $scaleX;
    +				$siX  = (int) $sX;
    +				$siX2 = (int) $sX + $scaleX2;
    +
    +				if ($isTrueColor) {
    +
    +					$c1 = ImageColorAt($src_img, $siX, $siY2);
    +					$c2 = ImageColorAt($src_img, $siX, $siY);
    +					$c3 = ImageColorAt($src_img, $siX2, $siY2);
    +					$c4 = ImageColorAt($src_img, $siX2, $siY);
    +
    +					$r = (( $c1             +  $c2             +  $c3             +  $c4            ) >> 2) & 0xFF0000;
    +					$g = ((($c1 & 0x00FF00) + ($c2 & 0x00FF00) + ($c3 & 0x00FF00) + ($c4 & 0x00FF00)) >> 2) & 0x00FF00;
    +					$b = ((($c1 & 0x0000FF) + ($c2 & 0x0000FF) + ($c3 & 0x0000FF) + ($c4 & 0x0000FF)) >> 2);
    +
    +				} else {
    +
    +					$c1 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY2));
    +					$c2 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX, $siY));
    +					$c3 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY2));
    +					$c4 = ImageColorsForIndex($src_img, ImageColorAt($src_img, $siX2, $siY));
    +
    +					$r = ($c1['red']   + $c2['red']   + $c3['red']   + $c4['red'] )  << 14;
    +					$g = ($c1['green'] + $c2['green'] + $c3['green'] + $c4['green']) <<  6;
    +					$b = ($c1['blue']  + $c2['blue']  + $c3['blue']  + $c4['blue'] ) >>  2;
    +
    +				}
    +				ImageSetPixel($dst_img, $dst_x + $x - $src_x, $dst_y + $y - $src_y, $r+$g+$b);
    +			}
    +		}
    +		return true;
    +	}
    +
    +
    +	function ImageCreateFunction($x_size, $y_size) {
    +		$ImageCreateFunction = 'ImageCreate';
    +		if (phpthumb_functions::gd_version() >= 2.0) {
    +			$ImageCreateFunction = 'ImageCreateTrueColor';
    +		}
    +		if (!function_exists($ImageCreateFunction)) {
    +			return phpthumb::ErrorImage($ImageCreateFunction.'() does not exist - no GD support?');
    +		}
    +		if (($x_size <= 0) || ($y_size <= 0)) {
    +			return phpthumb::ErrorImage('Invalid image dimensions: '.$ImageCreateFunction.'('.$x_size.', '.$y_size.')');
    +		}
    +		return $ImageCreateFunction($x_size, $y_size);
    +	}
    +
    +
    +	function ImageCopyRespectAlpha(&$dst_im, &$src_im, $dst_x, $dst_y, $src_x, $src_y, $src_w, $src_h, $pct=100) {
    +		for ($x = $src_x; $x < $src_w; $x++) {
    +			for ($y = $src_y; $y < $src_h; $y++) {
    +				$RealPixel    = phpthumb_functions::GetPixelColor($dst_im, $dst_x + $x, $dst_y + $y);
    +				$OverlayPixel = phpthumb_functions::GetPixelColor($src_im, $x, $y);
    +				$alphapct = $OverlayPixel['alpha'] / 127;
    +				$opacipct = $pct / 100;
    +				$overlaypct = (1 - $alphapct) * $opacipct;
    +
    +				$newcolor = phpthumb_functions::ImageColorAllocateAlphaSafe(
    +					$dst_im,
    +					round($RealPixel['red']   * (1 - $overlaypct)) + ($OverlayPixel['red']   * $overlaypct),
    +					round($RealPixel['green'] * (1 - $overlaypct)) + ($OverlayPixel['green'] * $overlaypct),
    +					round($RealPixel['blue']  * (1 - $overlaypct)) + ($OverlayPixel['blue']  * $overlaypct),
    +					//$RealPixel['alpha']);
    +					0);
    +
    +				ImageSetPixel($dst_im, $dst_x + $x, $dst_y + $y, $newcolor);
    +			}
    +		}
    +		return true;
    +	}
    +
    +
    +	function ProportionalResize($old_width, $old_height, $new_width=false, $new_height=false) {
    +		$old_aspect_ratio = $old_width / $old_height;
    +		if (($new_width === false) && ($new_height === false)) {
    +			return false;
    +		} elseif ($new_width === false) {
    +			$new_width = $new_height * $old_aspect_ratio;
    +		} elseif ($new_height === false) {
    +			$new_height = $new_width / $old_aspect_ratio;
    +		}
    +		$new_aspect_ratio = $new_width / $new_height;
    +		if ($new_aspect_ratio == $old_aspect_ratio) {
    +			// great, done
    +		} elseif ($new_aspect_ratio < $old_aspect_ratio) {
    +			// limited by width
    +			$new_height = $new_width / $old_aspect_ratio;
    +		} elseif ($new_aspect_ratio > $old_aspect_ratio) {
    +			// limited by height
    +			$new_width = $new_height * $old_aspect_ratio;
    +		}
    +		return array(round($new_width), round($new_height));
    +	}
    +
    +
    +	function FunctionIsDisabled($function) {
    +		static $DisabledFunctions = null;
    +		if (is_null($DisabledFunctions)) {
    +			$disable_functions_local  = explode(',',     @ini_get('disable_functions'));
    +			$disable_functions_global = explode(',', @get_cfg_var('disable_functions'));
    +			foreach ($disable_functions_local as $key => $value) {
    +				$DisabledFunctions[$value] = 'local';
    +			}
    +			foreach ($disable_functions_global as $key => $value) {
    +				$DisabledFunctions[$value] = 'global';
    +			}
    +			if (@ini_get('safe_mode')) {
    +				$DisabledFunctions['shell_exec'] = 'local';
    +			}
    +		}
    +		return isset($DisabledFunctions[$function]);
    +	}
    +
    +
    +	function SafeExec($command) {
    +		static $AllowedExecFunctions = array();
    +		if (empty($AllowedExecFunctions)) {
    +			$AllowedExecFunctions = array('shell_exec'=>true, 'passthru'=>true, 'system'=>true, 'exec'=>true);
    +			foreach ($AllowedExecFunctions as $key => $value) {
    +				$AllowedExecFunctions[$key] = !phpthumb_functions::FunctionIsDisabled($key);
    +			}
    +		}
    +		foreach ($AllowedExecFunctions as $execfunction => $is_allowed) {
    +			if (!$is_allowed) {
    +				continue;
    +			}
    +			switch ($execfunction) {
    +				case 'passthru':
    +					ob_start();
    +					$execfunction($command);
    +					$returnvalue = ob_get_contents();
    +					ob_end_clean();
    +					break;
    +
    +				case 'shell_exec':
    +				case 'system':
    +				case 'exec':
    +				default:
    +					ob_start();
    +					$returnvalue = $execfunction($command);
    +					ob_end_clean();
    +					break;
    +			}
    +			return $returnvalue;
    +		}
    +		return false;
    +	}
    +
    +
    +	function ApacheLookupURIarray($filename) {
    +		// apache_lookup_uri() only works when PHP is installed as an Apache module.
    +		if (php_sapi_name() == 'apache') {
    +			$keys = array('status', 'the_request', 'status_line', 'method', 'content_type', 'handler', 'uri', 'filename', 'path_info', 'args', 'boundary', 'no_cache', 'no_local_copy', 'allowed', 'send_bodyct', 'bytes_sent', 'byterange', 'clength', 'unparsed_uri', 'mtime', 'request_time');
    +			if ($apacheLookupURIobject = @apache_lookup_uri($filename)) {
    +				$apacheLookupURIarray = array();
    +				foreach ($keys as $key) {
    +					$apacheLookupURIarray[$key] = @$apacheLookupURIobject->$key;
    +				}
    +				return $apacheLookupURIarray;
    +			}
    +		}
    +		return false;
    +	}
    +
    +
    +	function gd_is_bundled() {
    +		static $isbundled = null;
    +		if (is_null($isbundled)) {
    +			$gd_info = gd_info();
    +			$isbundled = (strpos($gd_info['GD Version'], 'bundled') !== false);
    +		}
    +		return $isbundled;
    +	}
    +
    +
    +	function gd_version($fullstring=false) {
    +		static $cache_gd_version = array();
    +		if (empty($cache_gd_version)) {
    +			$gd_info = gd_info();
    +			if (eregi('bundled \((.+)\)$', $gd_info['GD Version'], $matches)) {
    +				$cache_gd_version[1] = $gd_info['GD Version'];  // e.g. "bundled (2.0.15 compatible)"
    +				$cache_gd_version[0] = (float) $matches[1];     // e.g. "2.0" (not "bundled (2.0.15 compatible)")
    +			} else {
    +				$cache_gd_version[1] = $gd_info['GD Version'];                       // e.g. "1.6.2 or higher"
    +				$cache_gd_version[0] = (float) substr($gd_info['GD Version'], 0, 3); // e.g. "1.6" (not "1.6.2 or higher")
    +			}
    +		}
    +		return $cache_gd_version[intval($fullstring)];
    +	}
    +
    +
    +	function filesize_remote($remotefile, $timeout=10) {
    +		$size = false;
    +		$url = parse_url($remotefile);
    +		if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) {
    +			fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n");
    +			if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) {
    +				stream_set_timeout($fp, $timeout);
    +			}
    +			while (!feof($fp)) {
    +				$headerline = fgets($fp, 4096);
    +				if (eregi('^Content-Length: (.*)', $headerline, $matches)) {
    +					$size = intval($matches[1]);
    +					break;
    +				}
    +			}
    +			fclose ($fp);
    +		}
    +		return $size;
    +	}
    +
    +
    +	function filedate_remote($remotefile, $timeout=10) {
    +		$date = false;
    +		$url = parse_url($remotefile);
    +		if ($fp = @fsockopen($url['host'], ($url['port'] ? $url['port'] : 80), $errno, $errstr, $timeout)) {
    +			fwrite($fp, 'HEAD '.@$url['path'].@$url['query'].' HTTP/1.0'."\r\n".'Host: '.@$url['host']."\r\n\r\n");
    +			if (phpthumb_functions::version_compare_replacement(phpversion(), '4.3.0', '>=')) {
    +				stream_set_timeout($fp, $timeout);
    +			}
    +			while (!feof($fp)) {
    +				$headerline = fgets($fp, 4096);
    +				if (eregi('^Last-Modified: (.*)', $headerline, $matches)) {
    +					$date = strtotime($matches[1]) - date('Z');
    +					break;
    +				}
    +			}
    +			fclose ($fp);
    +		}
    +		return $date;
    +	}
    +
    +
    +	function md5_file_safe($filename) {
    +		// md5_file() doesn't exist in PHP < 4.2.0
    +		if (function_exists('md5_file')) {
    +			return md5_file($filename);
    +		}
    +		if ($fp = @fopen($filename, 'rb')) {
    +			$rawData = '';
    +			do {
    +				$buffer = fread($fp, 8192);
    +				$rawData .= $buffer;
    +			} while (strlen($buffer) > 0);
    +			fclose($fp);
    +			return md5($rawData);
    +		}
    +		return false;
    +	}
    +
    +
    +	function nonempty_min() {
    +		$arg_list = func_get_args();
    +		$acceptable = array();
    +		foreach ($arg_list as $arg) {
    +			if ($arg) {
    +				$acceptable[] = $arg;
    +			}
    +		}
    +		return min($acceptable);
    +	}
    +
    +
    +	function LittleEndian2String($number, $minbytes=1) {
    +		$intstring = '';
    +		while ($number > 0) {
    +			$intstring = $intstring.chr($number & 255);
    +			$number >>= 8;
    +		}
    +		return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
    +	}
    +
    +	function OneOfThese() {
    +		// return the first useful (non-empty/non-zero/non-false) value from those passed
    +		$arg_list = func_get_args();
    +		foreach ($arg_list as $key => $value) {
    +			if ($value) {
    +				return $value;
    +			}
    +		}
    +		return false;
    +	}
    +
    +	function CaseInsensitiveInArray($needle, $haystack) {
    +		$needle = strtolower($needle);
    +		foreach ($haystack as $key => $value) {
    +			if (is_array($value)) {
    +				// skip?
    +			} elseif ($needle == strtolower($value)) {
    +				return true;
    +			}
    +		}
    +		return false;
    +	}
    +
    +	function URLreadFsock($host, $file, &$errstr, $successonly=true, $port=80, $timeout=10) {
    +		if (!function_exists('fsockopen') || phpthumb_functions::FunctionIsDisabled('fsockopen')) {
    +			$errstr = 'fsockopen() unavailable';
    +			return false;
    +		}
    +		if ($fp = @fsockopen($host, 80, $errno, $errstr, $timeout)) {
    +			$out  = 'GET '.$file.' HTTP/1.0'."\r\n";
    +			$out .= 'Host: '.$host."\r\n";
    +			$out .= 'Connection: Close'."\r\n\r\n";
    +			fwrite($fp, $out);
    +
    +			$isHeader = true;
    +			$Data_header = '';
    +			$Data_body   = '';
    +			$header_newlocation = '';
    +			while (!feof($fp)) {
    +				$line = fgets($fp, 1024);
    +				if ($isHeader) {
    +					$Data_header .= $line;
    +				} else {
    +					$Data_body .= $line;
    +				}
    +				if (eregi('^HTTP/[\\.0-9]+ ([0-9]+) (.+)$', rtrim($line), $matches)) {
    +					list($dummy, $errno, $errstr) = $matches;
    +					$errno = intval($errno);
    +				} elseif (eregi('^Location: (.*)$', rtrim($line), $matches)) {
    +					$header_newlocation = $matches[1];
    +				}
    +				if ($isHeader && ($line == "\r\n")) {
    +					$isHeader = false;
    +					if ($successonly) {
    +						switch ($errno) {
    +							case 200:
    +								// great, continue
    +								break;
    +
    +							default:
    +								$errstr = $errno.' '.$errstr.($header_newlocation ? '; Location: '.$header_newlocation : '');
    +								fclose($fp);
    +								return false;
    +								break;
    +						}
    +					}
    +				}
    +			}
    +			fclose($fp);
    +			return $Data_body;
    +		}
    +		return null;
    +	}
    +
    +	function CleanUpURLencoding($url, $queryseperator='&') {
    +		if (!eregi('^http', $url)) {
    +			return $url;
    +		}
    +		$parse_url = @parse_url($url);
    +		$pathelements = explode('/', $parse_url['path']);
    +		$CleanPathElements = array();
    +		$TranslationMatrix = array(' '=>'%20');
    +		foreach ($pathelements as $key => $pathelement) {
    +			$CleanPathElements[] = strtr($pathelement, $TranslationMatrix);
    +		}
    +		foreach ($CleanPathElements as $key => $value) {
    +			if (!$value) {
    +				unset($CleanPathElements[$key]);
    +			}
    +		}
    +
    +		$queries = explode($queryseperator, @$parse_url['query']);
    +		$CleanQueries = array();
    +		foreach ($queries as $key => $query) {
    +			@list($param, $value) = explode('=', $query);
    +			$CleanQueries[] = strtr($param, $TranslationMatrix).($value ? '='.strtr($value, $TranslationMatrix) : '');
    +		}
    +		foreach ($CleanQueries as $key => $value) {
    +			if (!$value) {
    +				unset($CleanQueries[$key]);
    +			}
    +		}
    +
    +		$cleaned_url  = $parse_url['scheme'].'://';
    +		$cleaned_url .= (@$parse_url['username'] ? $parse_url['host'].(@$parse_url['password'] ? ':'.$parse_url['password'] : '').'@' : '');
    +		$cleaned_url .= $parse_url['host'];
    +		$cleaned_url .= '/'.implode('/', $CleanPathElements);
    +		$cleaned_url .= (@$CleanQueries ? '?'.implode($queryseperator, $CleanQueries) : '');
    +		return $cleaned_url;
    +	}
    +
    +	function SafeURLread($url, &$error, $timeout=10, $followredirects=true) {
    +		$error = '';
    +
    +		$parsed_url = @parse_url($url);
    +		$alreadyLookedAtURLs[trim($url)] = true;
    +		do {
    +			$rawData = phpthumb_functions::URLreadFsock(@$parsed_url['host'], @$parsed_url['path'].'?'.@$parsed_url['query'], $errstr, true, (@$parsed_url['port'] ? @$parsed_url['port'] : 80), $timeout);
    +			if (eregi('302 Found; Location\\: (http.*)', $errstr, $matches)) {
    +				$matches[1] = trim(@$matches[1]);
    +				if ($alreadyLookedAtURLs[$matches[1]]) {
    +					break;
    +				}
    +				$alreadyLookedAtURLs[$matches[1]] = true;
    +				$parsed_url = @parse_url($matches[1]);
    +			} else {
    +				break;
    +			}
    +		} while (true);
    +		$error .= 'Error opening "'.$url.'":'."\n\n".$errstr;
    +		if ($rawData === false) {
    +			return false;
    +		} elseif ($rawData === null) {
    +			// fall through
    +		} else {
    +			return $rawData;
    +		}
    +
    +		if (function_exists('curl_version') && !phpthumb_functions::FunctionIsDisabled('curl_exec')) {
    +			$ch = curl_init();
    +			curl_setopt($ch, CURLOPT_URL, $url);
    +			curl_setopt($ch, CURLOPT_HEADER, false);
    +			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    +			curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
    +			curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    +			$rawData = curl_exec($ch);
    +			curl_close($ch);
    +			if (strlen($rawData) > 0) {
    +				return $rawData;
    +			}
    +			$error .= 'CURL available but returned no data; ';
    +		} else {
    +			$error .= 'CURL unavailable; ';
    +		}
    +
    +		$BrokenURLfopenPHPversions = array('4.4.2');
    +		if (in_array(phpversion(), $BrokenURLfopenPHPversions)) {
    +			$error .= 'fopen(URL) broken in PHP v'.phpversion().'; ';
    +		} elseif (@ini_get('allow_url_fopen')) {
    +			$rawData = '';
    +			ob_start();
    +			if ($fp = fopen($url, 'rb')) {
    +				do {
    +					$buffer = fread($fp, 8192);
    +					$rawData .= $buffer;
    +				} while (strlen($buffer) > 0);
    +				fclose($fp);
    +			} else {
    +				$error .= trim(strip_tags(ob_get_contents()));
    +			}
    +			ob_end_clean();
    +			if (!$error) {
    +				return $rawData;
    +			}
    +			$error .= '; "allow_url_fopen" enabled but returned no data; ';
    +		} else {
    +			$error .= '"allow_url_fopen" disabled; ';
    +		}
    +
    +		return false;
    +	}
    +
    +	function EnsureDirectoryExists($dirname) {
    +		$directory_elements = explode(DIRECTORY_SEPARATOR, $dirname);
    +		$startoffset = (!$directory_elements[0] ? 2 : 1);  // unix with leading "/" then start with 2nd element; Windows with leading "c:\" then start with 1st element
    +		$open_basedirs = explode(':', ini_get('open_basedir'));
    +		foreach ($open_basedirs as $key => $open_basedir) {
    +			if (ereg('^'.preg_quote($open_basedir), $dirname) && (strlen($dirname) > strlen($open_basedir))) {
    +				$startoffset = count(explode(DIRECTORY_SEPARATOR, $open_basedir));
    +				break;
    +			}
    +		}
    +		$i = $startoffset;
    +		$endoffset = count($directory_elements);
    +		for ($i = $startoffset; $i <= $endoffset; $i++) {
    +			$test_directory = implode(DIRECTORY_SEPARATOR, array_slice($directory_elements, 0, $i));
    +			if (!$test_directory) {
    +				continue;
    +			}
    +			if (!@is_dir($test_directory)) {
    +				if (@file_exists($test_directory)) {
    +					// directory name already exists as a file
    +					return false;
    +				}
    +				@mkdir($test_directory, 0755);
    +				@chmod($test_directory, 0755);
    +				if (!@is_dir($test_directory) || !@is_writeable($test_directory)) {
    +					return false;
    +				}
    +			}
    +		}
    +		return true;
    +	}
    +
    +
    +	function GetAllFilesInSubfolders($dirname) {
    +		$AllFiles = array();
    +		$dirname = rtrim(realpath($dirname), '/\\');
    +		if ($dirhandle = @opendir($dirname)) {
    +			while ($file = readdir($dirhandle)) {
    +				$fullfilename = $dirname.DIRECTORY_SEPARATOR.$file;
    +				if (is_file($fullfilename)) {
    +					$AllFiles[] = $fullfilename;
    +				} elseif (is_dir($fullfilename)) {
    +					if (($file == '.') || ($file == '..')) {
    +						continue;
    +					}
    +					$subfiles = phpthumb_functions::GetAllFilesInSubfolders($fullfilename);
    +					foreach ($subfiles as $filename) {
    +						$AllFiles[] = $filename;
    +					}
    +				} else {
    +					// ignore?
    +				}
    +			}
    +			closedir($dirhandle);
    +		}
    +		sort($AllFiles);
    +		return array_unique($AllFiles);
    +	}
    +
    +
    +	function SanitizeFilename($filename) {
    +		$filename = ereg_replace('[^'.preg_quote(' !#$%^()+,-.;<>=@[]_{}').'a-zA-Z0-9]', '_', $filename);
    +		if (phpthumb_functions::version_compare_replacement(phpversion(), '4.1.0', '>=')) {
    +			$filename = trim($filename, '.');
    +		}
    +		return $filename;
    +	}
    +
    +}
    +
    +
    +////////////// END: class phpthumb_functions //////////////
    +
    +
    +if (!function_exists('gd_info')) {
    +	// built into PHP v4.3.0+ (with bundled GD2 library)
    +	function gd_info() {
    +		static $gd_info = array();
    +		if (empty($gd_info)) {
    +			// based on code by johnschaefer at gmx dot de
    +			// from PHP help on gd_info()
    +			$gd_info = array(
    +				'GD Version'         => '',
    +				'FreeType Support'   => false,
    +				'FreeType Linkage'   => '',
    +				'T1Lib Support'      => false,
    +				'GIF Read Support'   => false,
    +				'GIF Create Support' => false,
    +				'JPG Support'        => false,
    +				'PNG Support'        => false,
    +				'WBMP Support'       => false,
    +				'XBM Support'        => false
    +			);
    +			$phpinfo_array = phpthumb_functions::phpinfo_array();
    +			foreach ($phpinfo_array as $line) {
    +				$line = trim(strip_tags($line));
    +				foreach ($gd_info as $key => $value) {
    +					//if (strpos($line, $key) !== false) {
    +					if (strpos($line, $key) === 0) {
    +						$newvalue = trim(str_replace($key, '', $line));
    +						$gd_info[$key] = $newvalue;
    +					}
    +				}
    +			}
    +			if (empty($gd_info['GD Version'])) {
    +				// probable cause: "phpinfo() disabled for security reasons"
    +				if (function_exists('ImageTypes')) {
    +					$imagetypes = ImageTypes();
    +					if ($imagetypes & IMG_PNG) {
    +						$gd_info['PNG Support'] = true;
    +					}
    +					if ($imagetypes & IMG_GIF) {
    +						$gd_info['GIF Create Support'] = true;
    +					}
    +					if ($imagetypes & IMG_JPG) {
    +						$gd_info['JPG Support'] = true;
    +					}
    +					if ($imagetypes & IMG_WBMP) {
    +						$gd_info['WBMP Support'] = true;
    +					}
    +				}
    +				// to determine capability of GIF creation, try to use ImageCreateFromGIF on a 1px GIF
    +				if (function_exists('ImageCreateFromGIF')) {
    +					if ($tempfilename = phpthumb::phpThumb_tempnam()) {
    +						if ($fp_tempfile = @fopen($tempfilename, 'wb')) {
    +							fwrite($fp_tempfile, base64_decode('R0lGODlhAQABAIAAAH//AP///ywAAAAAAQABAAACAUQAOw==')); // very simple 1px GIF file base64-encoded as string
    +							fclose($fp_tempfile);
    +
    +							// if we can convert the GIF file to a GD image then GIF create support must be enabled, otherwise it's not
    +							$gd_info['GIF Read Support'] = (bool) @ImageCreateFromGIF($tempfilename);
    +						}
    +						unlink($tempfilename);
    +					}
    +				}
    +				if (function_exists('ImageCreateTrueColor') && @ImageCreateTrueColor(1, 1)) {
    +					$gd_info['GD Version'] = '2.0.1 or higher (assumed)';
    +				} elseif (function_exists('ImageCreate') && @ImageCreate(1, 1)) {
    +					$gd_info['GD Version'] = '1.6.0 or higher (assumed)';
    +				}
    +			}
    +		}
    +		return $gd_info;
    +	}
    +}
    +
    +
    +if (!function_exists('is_executable')) {
    +	// in PHP v3+, but v5.0+ for Windows
    +	function is_executable($filename) {
    +		// poor substitute, but better than nothing
    +		return file_exists($filename);
    +	}
    +}
    +
    +
    +if (!function_exists('preg_quote')) {
    +	// included in PHP v3.0.9+, but may be unavailable if not compiled in
    +	function preg_quote($string, $delimiter='\\') {
    +		static $preg_quote_array = array();
    +		if (empty($preg_quote_array)) {
    +			$escapeables = '.\\+*?[^]$(){}=!<>|:';
    +			for ($i = 0; $i < strlen($escapeables); $i++) {
    +				$strtr_preg_quote[$escapeables{$i}] = $delimiter.$escapeables{$i};
    +			}
    +		}
    +		return strtr($string, $strtr_preg_quote);
    +	}
    +}
    +
    +if (!function_exists('file_get_contents')) {
    +	// included in PHP v4.3.0+
    +	function file_get_contents($filename) {
    +		if (eregi('^(f|ht)tp\://', $filename)) {
    +			return SafeURLread($filename, $error);
    +		}
    +		if ($fp = @fopen($filename, 'rb')) {
    +			$rawData = '';
    +			do {
    +				$buffer = fread($fp, 8192);
    +				$rawData .= $buffer;
    +			} while (strlen($buffer) > 0);
    +			fclose($fp);
    +			return $rawData;
    +		}
    +		return false;
    +	}
    +}
    +
    +
    +if (!function_exists('file_put_contents')) {
    +	// included in PHP v5.0.0+
    +	function file_put_contents($filename, $filedata) {
    +		if ($fp = @fopen($filename, 'wb')) {
    +			fwrite($fp, $filedata);
    +			fclose($fp);
    +			return true;
    +		}
    +		return false;
    +	}
    +}
    +
    +if (!function_exists('imagealphablending')) {
    +	// built-in function requires PHP v4.0.6+ *and* GD v2.0.1+
    +	function imagealphablending(&$img, $blendmode=true) {
    +		// do nothing, this function is declared here just to
    +		// prevent runtime errors if GD2 is not available
    +		return true;
    +	}
    +}
    +
    +if (!function_exists('imagesavealpha')) {
    +	// built-in function requires PHP v4.3.2+ *and* GD v2.0.1+
    +	function imagesavealpha(&$img, $blendmode=true) {
    +		// do nothing, this function is declared here just to
    +		// prevent runtime errors if GD2 is not available
    +		return true;
    +	}
    +}
    +
    +?>
    \ No newline at end of file
    diff --git a/common/phpThumb/phpthumb.gif.php b/common/phpThumb/phpthumb.gif.php
    new file mode 100644
    index 0000000..b5a7fb1
    --- /dev/null
    +++ b/common/phpThumb/phpthumb.gif.php
    @@ -0,0 +1,1168 @@
    +  = gif_loadFile(filename, [index])
    +//  = gif_getSize( or filename, &width, &height)
    +//  = gif_outputAsPng(, filename, [bgColor])
    +//  = gif_outputAsBmp(, filename, [bgcolor])
    +//  = gif_outputAsJpeg(, filename, [bgcolor]) - use cjpeg if available otherwise uses GD
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +// Original code by Fabien Ezber
    +// Modified by James Heinrich  for use in phpThumb() - December 10, 2003
    +// * Added function gif_loadFileToGDimageResource() - this returns a GD image resource
    +// * Modified gif_outputAsJpeg() to check if it's running under Windows, or if cjpeg is not
    +//   available, in which case it will attempt to output JPEG using GD functions
    +// * added @ error-suppression to two lines where it checks: if ($this->m_img->m_bTrans)
    +//   otherwise warnings are generated if error_reporting == E_ALL
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +function gif_loadFile($lpszFileName, $iIndex = 0)
    +{
    +	$gif = new CGIF();
    +	if ($gif->loadFile($lpszFileName, $iIndex)) {
    +		return $gif;
    +	}
    +	return false;
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +// Added by James Heinrich  - December 10, 2003
    +function gif_loadFileToGDimageResource($gifFilename, $bgColor = -1)
    +{
    +	if ($gif = gif_loadFile($gifFilename)) {
    +
    +		@set_time_limit(300);
    +		// general strategy: convert raw data to PNG then convert PNG data to GD image resource
    +		$PNGdata = $gif->getPng($bgColor);
    +		if ($img = @ImageCreateFromString($PNGdata)) {
    +
    +			// excellent - PNG image data successfully converted to GD image
    +			return $img;
    +
    +		} elseif ($img = $gif->getGD_PixelPlotterVersion()) {
    +
    +			// problem: ImageCreateFromString() didn't like the PNG image data.
    +			//   This has been known to happen in PHP v4.0.6
    +			// solution: take the raw image data and create a new GD image and plot
    +			//   pixel-by-pixel on the GD image. This is extremely slow, but it does
    +			//   work and a slow solution is better than no solution, right? :)
    +			return $img;
    +
    +		}
    +	}
    +	return false;
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +function gif_outputAsBmp($gif, $lpszFileName, $bgColor = -1)
    +{
    +	if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) {
    +		return false;
    +	}
    +
    +	$fd = $gif->getBmp($bgColor);
    +	if (strlen($fd) <= 0) {
    +		return false;
    +	}
    +
    +	if (!($fh = @fopen($lpszFileName, 'wb'))) {
    +		return false;
    +	}
    +	@fwrite($fh, $fd, strlen($fd));
    +	@fflush($fh);
    +	@fclose($fh);
    +	return true;
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +function gif_outputAsPng($gif, $lpszFileName, $bgColor = -1)
    +{
    +	if (!isSet($gif) || (@get_class($gif) <> 'cgif') || !$gif->loaded() || ($lpszFileName == '')) {
    +		return false;
    +	}
    +
    +	$fd = $gif->getPng($bgColor);
    +	if (strlen($fd) <= 0) {
    +		return false;
    +	}
    +
    +	if (!($fh = @fopen($lpszFileName, 'wb'))) {
    +		return false;
    +	}
    +	@fwrite($fh, $fd, strlen($fd));
    +	@fflush($fh);
    +	@fclose($fh);
    +	return true;
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +function gif_outputAsJpeg($gif, $lpszFileName, $bgColor = -1)
    +{
    +	// JPEG output that does not require cjpeg added by James Heinrich  - December 10, 2003
    +	if ((strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') && (file_exists('/usr/local/bin/cjpeg') || `which cjpeg`)) {
    +
    +		if (gif_outputAsBmp($gif, $lpszFileName.'.bmp', $bgColor)) {
    +			exec('cjpeg '.$lpszFileName.'.bmp >'.$lpszFileName.' 2>/dev/null');
    +			@unLink($lpszFileName.'.bmp');
    +
    +			if (@file_exists($lpszFileName)) {
    +				if (@fileSize($lpszFileName) > 0) {
    +					return true;
    +				}
    +
    +				@unLink($lpszFileName);
    +			}
    +		}
    +
    +	} else {
    +
    +		// either Windows, or cjpeg not found in path
    +		if ($img = @ImageCreateFromString($gif->getPng($bgColor))) {
    +			if (@ImageJPEG($img, $lpszFileName)) {
    +				return true;
    +			}
    +		}
    +
    +	}
    +
    +	return false;
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +function gif_getSize($gif, &$width, &$height)
    +{
    +	if (isSet($gif) && (@get_class($gif) == 'cgif') && $gif->loaded()) {
    +		$width  = $gif->width();
    +		$height = $gif->height();
    +	} elseif (@file_exists($gif)) {
    +		$myGIF = new CGIF();
    +		if (!$myGIF->getSize($gif, $width, $height)) {
    +			return false;
    +		}
    +	} else {
    +		return false;
    +	}
    +
    +	return true;
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +class CGIFLZW
    +{
    +	var $MAX_LZW_BITS;
    +	var $Fresh, $CodeSize, $SetCodeSize, $MaxCode, $MaxCodeSize, $FirstCode, $OldCode;
    +	var $ClearCode, $EndCode, $Next, $Vals, $Stack, $sp, $Buf, $CurBit, $LastBit, $Done, $LastByte;
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	// CONSTRUCTOR
    +	function CGIFLZW()
    +	{
    +		$this->MAX_LZW_BITS = 12;
    +		unSet($this->Next);
    +		unSet($this->Vals);
    +		unSet($this->Stack);
    +		unSet($this->Buf);
    +
    +		$this->Next  = range(0, (1 << $this->MAX_LZW_BITS)       - 1);
    +		$this->Vals  = range(0, (1 << $this->MAX_LZW_BITS)       - 1);
    +		$this->Stack = range(0, (1 << ($this->MAX_LZW_BITS + 1)) - 1);
    +		$this->Buf   = range(0, 279);
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function deCompress($data, &$datLen)
    +	{
    +		$stLen  = strlen($data);
    +		$datLen = 0;
    +		$ret    = '';
    +
    +		// INITIALIZATION
    +		$this->LZWCommand($data, true);
    +
    +		while (($iIndex = $this->LZWCommand($data, false)) >= 0) {
    +			$ret .= chr($iIndex);
    +		}
    +
    +		$datLen = $stLen - strlen($data);
    +
    +		if ($iIndex != -2) {
    +			return false;
    +		}
    +
    +		return $ret;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function LZWCommand(&$data, $bInit)
    +	{
    +		if ($bInit) {
    +			$this->SetCodeSize = ord($data{0});
    +			$data = substr($data, 1);
    +
    +			$this->CodeSize    = $this->SetCodeSize + 1;
    +			$this->ClearCode   = 1 << $this->SetCodeSize;
    +			$this->EndCode     = $this->ClearCode + 1;
    +			$this->MaxCode     = $this->ClearCode + 2;
    +			$this->MaxCodeSize = $this->ClearCode << 1;
    +
    +			$this->GetCode($data, $bInit);
    +
    +			$this->Fresh = 1;
    +			for ($i = 0; $i < $this->ClearCode; $i++) {
    +				$this->Next[$i] = 0;
    +				$this->Vals[$i] = $i;
    +			}
    +
    +			for (; $i < (1 << $this->MAX_LZW_BITS); $i++) {
    +				$this->Next[$i] = 0;
    +				$this->Vals[$i] = 0;
    +			}
    +
    +			$this->sp = 0;
    +			return 1;
    +		}
    +
    +		if ($this->Fresh) {
    +			$this->Fresh = 0;
    +			do {
    +				$this->FirstCode = $this->GetCode($data, $bInit);
    +				$this->OldCode   = $this->FirstCode;
    +			}
    +			while ($this->FirstCode == $this->ClearCode);
    +
    +			return $this->FirstCode;
    +		}
    +
    +		if ($this->sp > 0) {
    +			$this->sp--;
    +			return $this->Stack[$this->sp];
    +		}
    +
    +		while (($Code = $this->GetCode($data, $bInit)) >= 0) {
    +			if ($Code == $this->ClearCode) {
    +				for ($i = 0; $i < $this->ClearCode; $i++) {
    +					$this->Next[$i] = 0;
    +					$this->Vals[$i] = $i;
    +				}
    +
    +				for (; $i < (1 << $this->MAX_LZW_BITS); $i++) {
    +					$this->Next[$i] = 0;
    +					$this->Vals[$i] = 0;
    +				}
    +
    +				$this->CodeSize    = $this->SetCodeSize + 1;
    +				$this->MaxCodeSize = $this->ClearCode << 1;
    +				$this->MaxCode     = $this->ClearCode + 2;
    +				$this->sp          = 0;
    +				$this->FirstCode   = $this->GetCode($data, $bInit);
    +				$this->OldCode     = $this->FirstCode;
    +
    +				return $this->FirstCode;
    +			}
    +
    +			if ($Code == $this->EndCode) {
    +				return -2;
    +			}
    +
    +			$InCode = $Code;
    +			if ($Code >= $this->MaxCode) {
    +				$this->Stack[$this->sp] = $this->FirstCode;
    +				$this->sp++;
    +				$Code = $this->OldCode;
    +			}
    +
    +			while ($Code >= $this->ClearCode) {
    +				$this->Stack[$this->sp] = $this->Vals[$Code];
    +				$this->sp++;
    +
    +				if ($Code == $this->Next[$Code]) // Circular table entry, big GIF Error!
    +					return -1;
    +
    +				$Code = $this->Next[$Code];
    +			}
    +
    +			$this->FirstCode = $this->Vals[$Code];
    +			$this->Stack[$this->sp] = $this->FirstCode;
    +			$this->sp++;
    +
    +			if (($Code = $this->MaxCode) < (1 << $this->MAX_LZW_BITS)) {
    +				$this->Next[$Code] = $this->OldCode;
    +				$this->Vals[$Code] = $this->FirstCode;
    +				$this->MaxCode++;
    +
    +				if (($this->MaxCode >= $this->MaxCodeSize) && ($this->MaxCodeSize < (1 << $this->MAX_LZW_BITS))) {
    +					$this->MaxCodeSize *= 2;
    +					$this->CodeSize++;
    +				}
    +			}
    +
    +			$this->OldCode = $InCode;
    +			if ($this->sp > 0) {
    +				$this->sp--;
    +				return $this->Stack[$this->sp];
    +			}
    +		}
    +
    +		return $Code;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function GetCode(&$data, $bInit)
    +	{
    +		if ($bInit) {
    +			$this->CurBit   = 0;
    +			$this->LastBit  = 0;
    +			$this->Done     = 0;
    +			$this->LastByte = 2;
    +			return 1;
    +		}
    +
    +		if (($this->CurBit + $this->CodeSize) >= $this->LastBit) {
    +			if ($this->Done) {
    +				if ($this->CurBit >= $this->LastBit) {
    +					// Ran off the end of my bits
    +					return 0;
    +				}
    +				return -1;
    +			}
    +
    +			$this->Buf[0] = $this->Buf[$this->LastByte - 2];
    +			$this->Buf[1] = $this->Buf[$this->LastByte - 1];
    +
    +			$Count = ord($data{0});
    +			$data  = substr($data, 1);
    +
    +			if ($Count) {
    +				for ($i = 0; $i < $Count; $i++) {
    +					$this->Buf[2 + $i] = ord($data{$i});
    +				}
    +				$data = substr($data, $Count);
    +			} else {
    +				$this->Done = 1;
    +			}
    +
    +			$this->LastByte = 2 + $Count;
    +			$this->CurBit   = ($this->CurBit - $this->LastBit) + 16;
    +			$this->LastBit  = (2 + $Count) << 3;
    +		}
    +
    +		$iRet = 0;
    +		for ($i = $this->CurBit, $j = 0; $j < $this->CodeSize; $i++, $j++) {
    +			$iRet |= (($this->Buf[intval($i / 8)] & (1 << ($i % 8))) != 0) << $j;
    +		}
    +
    +		$this->CurBit += $this->CodeSize;
    +		return $iRet;
    +	}
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +class CGIFCOLORTABLE
    +{
    +	var $m_nColors;
    +	var $m_arColors;
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	// CONSTRUCTOR
    +	function CGIFCOLORTABLE()
    +	{
    +		unSet($this->m_nColors);
    +		unSet($this->m_arColors);
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function load($lpData, $num)
    +	{
    +		$this->m_nColors  = 0;
    +		$this->m_arColors = array();
    +
    +		for ($i = 0; $i < $num; $i++) {
    +			$rgb = substr($lpData, $i * 3, 3);
    +			if (strlen($rgb) < 3) {
    +				return false;
    +			}
    +
    +			$this->m_arColors[] = (ord($rgb{2}) << 16) + (ord($rgb{1}) << 8) + ord($rgb{0});
    +			$this->m_nColors++;
    +		}
    +
    +		return true;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function toString()
    +	{
    +		$ret = '';
    +
    +		for ($i = 0; $i < $this->m_nColors; $i++) {
    +			$ret .=
    +				chr(($this->m_arColors[$i] & 0x000000FF))       . // R
    +				chr(($this->m_arColors[$i] & 0x0000FF00) >>  8) . // G
    +				chr(($this->m_arColors[$i] & 0x00FF0000) >> 16);  // B
    +		}
    +
    +		return $ret;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function toRGBQuad()
    +	{
    +		$ret = '';
    +
    +		for ($i = 0; $i < $this->m_nColors; $i++) {
    +			$ret .=
    +				chr(($this->m_arColors[$i] & 0x00FF0000) >> 16) . // B
    +				chr(($this->m_arColors[$i] & 0x0000FF00) >>  8) . // G
    +				chr(($this->m_arColors[$i] & 0x000000FF))       . // R
    +				"\x00";
    +		}
    +
    +		return $ret;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function colorIndex($rgb)
    +	{
    +		$rgb  = intval($rgb) & 0xFFFFFF;
    +		$r1   = ($rgb & 0x0000FF);
    +		$g1   = ($rgb & 0x00FF00) >>  8;
    +		$b1   = ($rgb & 0xFF0000) >> 16;
    +		$idx  = -1;
    +
    +		for ($i = 0; $i < $this->m_nColors; $i++) {
    +			$r2 = ($this->m_arColors[$i] & 0x000000FF);
    +			$g2 = ($this->m_arColors[$i] & 0x0000FF00) >>  8;
    +			$b2 = ($this->m_arColors[$i] & 0x00FF0000) >> 16;
    +			$d  = abs($r2 - $r1) + abs($g2 - $g1) + abs($b2 - $b1);
    +
    +			if (($idx == -1) || ($d < $dif)) {
    +				$idx = $i;
    +				$dif = $d;
    +			}
    +		}
    +
    +		return $idx;
    +	}
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +class CGIFFILEHEADER
    +{
    +	var $m_lpVer;
    +	var $m_nWidth;
    +	var $m_nHeight;
    +	var $m_bGlobalClr;
    +	var $m_nColorRes;
    +	var $m_bSorted;
    +	var $m_nTableSize;
    +	var $m_nBgColor;
    +	var $m_nPixelRatio;
    +	var $m_colorTable;
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	// CONSTRUCTOR
    +	function CGIFFILEHEADER()
    +	{
    +		unSet($this->m_lpVer);
    +		unSet($this->m_nWidth);
    +		unSet($this->m_nHeight);
    +		unSet($this->m_bGlobalClr);
    +		unSet($this->m_nColorRes);
    +		unSet($this->m_bSorted);
    +		unSet($this->m_nTableSize);
    +		unSet($this->m_nBgColor);
    +		unSet($this->m_nPixelRatio);
    +		unSet($this->m_colorTable);
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function load($lpData, &$hdrLen)
    +	{
    +		$hdrLen = 0;
    +
    +		$this->m_lpVer = substr($lpData, 0, 6);
    +		if (($this->m_lpVer <> 'GIF87a') && ($this->m_lpVer <> 'GIF89a')) {
    +			return false;
    +		}
    +
    +		$this->m_nWidth  = $this->w2i(substr($lpData, 6, 2));
    +		$this->m_nHeight = $this->w2i(substr($lpData, 8, 2));
    +		if (!$this->m_nWidth || !$this->m_nHeight) {
    +			return false;
    +		}
    +
    +		$b = ord(substr($lpData, 10, 1));
    +		$this->m_bGlobalClr  = ($b & 0x80) ? true : false;
    +		$this->m_nColorRes   = ($b & 0x70) >> 4;
    +		$this->m_bSorted     = ($b & 0x08) ? true : false;
    +		$this->m_nTableSize  = 2 << ($b & 0x07);
    +		$this->m_nBgColor    = ord(substr($lpData, 11, 1));
    +		$this->m_nPixelRatio = ord(substr($lpData, 12, 1));
    +		$hdrLen = 13;
    +
    +		if ($this->m_bGlobalClr) {
    +			$this->m_colorTable = new CGIFCOLORTABLE();
    +			if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) {
    +				return false;
    +			}
    +			$hdrLen += 3 * $this->m_nTableSize;
    +		}
    +
    +		return true;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function w2i($str)
    +	{
    +		return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
    +	}
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +class CGIFIMAGEHEADER
    +{
    +	var $m_nLeft;
    +	var $m_nTop;
    +	var $m_nWidth;
    +	var $m_nHeight;
    +	var $m_bLocalClr;
    +	var $m_bInterlace;
    +	var $m_bSorted;
    +	var $m_nTableSize;
    +	var $m_colorTable;
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	// CONSTRUCTOR
    +	function CGIFIMAGEHEADER()
    +	{
    +		unSet($this->m_nLeft);
    +		unSet($this->m_nTop);
    +		unSet($this->m_nWidth);
    +		unSet($this->m_nHeight);
    +		unSet($this->m_bLocalClr);
    +		unSet($this->m_bInterlace);
    +		unSet($this->m_bSorted);
    +		unSet($this->m_nTableSize);
    +		unSet($this->m_colorTable);
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function load($lpData, &$hdrLen)
    +	{
    +		$hdrLen = 0;
    +
    +		$this->m_nLeft   = $this->w2i(substr($lpData, 0, 2));
    +		$this->m_nTop    = $this->w2i(substr($lpData, 2, 2));
    +		$this->m_nWidth  = $this->w2i(substr($lpData, 4, 2));
    +		$this->m_nHeight = $this->w2i(substr($lpData, 6, 2));
    +
    +		if (!$this->m_nWidth || !$this->m_nHeight) {
    +			return false;
    +		}
    +
    +		$b = ord($lpData{8});
    +		$this->m_bLocalClr  = ($b & 0x80) ? true : false;
    +		$this->m_bInterlace = ($b & 0x40) ? true : false;
    +		$this->m_bSorted    = ($b & 0x20) ? true : false;
    +		$this->m_nTableSize = 2 << ($b & 0x07);
    +		$hdrLen = 9;
    +
    +		if ($this->m_bLocalClr) {
    +			$this->m_colorTable = new CGIFCOLORTABLE();
    +			if (!$this->m_colorTable->load(substr($lpData, $hdrLen), $this->m_nTableSize)) {
    +				return false;
    +			}
    +			$hdrLen += 3 * $this->m_nTableSize;
    +		}
    +
    +		return true;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function w2i($str)
    +	{
    +		return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
    +	}
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +class CGIFIMAGE
    +{
    +	var $m_disp;
    +	var $m_bUser;
    +	var $m_bTrans;
    +	var $m_nDelay;
    +	var $m_nTrans;
    +	var $m_lpComm;
    +	var $m_gih;
    +	var $m_data;
    +	var $m_lzw;
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function CGIFIMAGE()
    +	{
    +		unSet($this->m_disp);
    +		unSet($this->m_bUser);
    +		unSet($this->m_bTrans);
    +		unSet($this->m_nDelay);
    +		unSet($this->m_nTrans);
    +		unSet($this->m_lpComm);
    +		unSet($this->m_data);
    +		$this->m_gih = new CGIFIMAGEHEADER();
    +		$this->m_lzw = new CGIFLZW();
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function load($data, &$datLen)
    +	{
    +		$datLen = 0;
    +
    +		while (true) {
    +			$b = ord($data{0});
    +			$data = substr($data, 1);
    +			$datLen++;
    +
    +			switch($b) {
    +			case 0x21: // Extension
    +				if (!$this->skipExt($data, $len = 0)) {
    +					return false;
    +				}
    +				$datLen += $len;
    +				break;
    +
    +			case 0x2C: // Image
    +				// LOAD HEADER & COLOR TABLE
    +				if (!$this->m_gih->load($data, $len = 0)) {
    +					return false;
    +				}
    +				$data = substr($data, $len);
    +				$datLen += $len;
    +
    +				// ALLOC BUFFER
    +				if (!($this->m_data = $this->m_lzw->deCompress($data, $len = 0))) {
    +					return false;
    +				}
    +				$data = substr($data, $len);
    +				$datLen += $len;
    +
    +				if ($this->m_gih->m_bInterlace) {
    +					$this->deInterlace();
    +				}
    +				return true;
    +
    +			case 0x3B: // EOF
    +			default:
    +				return false;
    +			}
    +		}
    +		return false;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function skipExt(&$data, &$extLen)
    +	{
    +		$extLen = 0;
    +
    +		$b = ord($data{0});
    +		$data = substr($data, 1);
    +		$extLen++;
    +
    +		switch($b) {
    +		case 0xF9: // Graphic Control
    +			$b = ord($data{1});
    +			$this->m_disp   = ($b & 0x1C) >> 2;
    +			$this->m_bUser  = ($b & 0x02) ? true : false;
    +			$this->m_bTrans = ($b & 0x01) ? true : false;
    +			$this->m_nDelay = $this->w2i(substr($data, 2, 2));
    +			$this->m_nTrans = ord($data{4});
    +			break;
    +
    +		case 0xFE: // Comment
    +			$this->m_lpComm = substr($data, 1, ord($data{0}));
    +			break;
    +
    +		case 0x01: // Plain text
    +			break;
    +
    +		case 0xFF: // Application
    +			break;
    +		}
    +
    +		// SKIP DEFAULT AS DEFS MAY CHANGE
    +		$b = ord($data{0});
    +		$data = substr($data, 1);
    +		$extLen++;
    +		while ($b > 0) {
    +			$data = substr($data, $b);
    +			$extLen += $b;
    +			$b    = ord($data{0});
    +			$data = substr($data, 1);
    +			$extLen++;
    +		}
    +		return true;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function w2i($str)
    +	{
    +		return ord(substr($str, 0, 1)) + (ord(substr($str, 1, 1)) << 8);
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function deInterlace()
    +	{
    +		$data = $this->m_data;
    +
    +		for ($i = 0; $i < 4; $i++) {
    +			switch($i) {
    +			case 0:
    +				$s = 8;
    +				$y = 0;
    +				break;
    +
    +			case 1:
    +				$s = 8;
    +				$y = 4;
    +				break;
    +
    +			case 2:
    +				$s = 4;
    +				$y = 2;
    +				break;
    +
    +			case 3:
    +				$s = 2;
    +				$y = 1;
    +				break;
    +			}
    +
    +			for (; $y < $this->m_gih->m_nHeight; $y += $s) {
    +				$lne = substr($this->m_data, 0, $this->m_gih->m_nWidth);
    +				$this->m_data = substr($this->m_data, $this->m_gih->m_nWidth);
    +
    +				$data =
    +					substr($data, 0, $y * $this->m_gih->m_nWidth) .
    +					$lne .
    +					substr($data, ($y + 1) * $this->m_gih->m_nWidth);
    +			}
    +		}
    +
    +		$this->m_data = $data;
    +	}
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +class CGIF
    +{
    +	var $m_gfh;
    +	var $m_lpData;
    +	var $m_img;
    +	var $m_bLoaded;
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	// CONSTRUCTOR
    +	function CGIF()
    +	{
    +		$this->m_gfh     = new CGIFFILEHEADER();
    +		$this->m_img     = new CGIFIMAGE();
    +		$this->m_lpData  = '';
    +		$this->m_bLoaded = false;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function loadFile($lpszFileName, $iIndex)
    +	{
    +		if ($iIndex < 0) {
    +			return false;
    +		}
    +
    +		// READ FILE
    +		if (!($fh = @fopen($lpszFileName, 'rb'))) {
    +			return false;
    +		}
    +		$this->m_lpData = @fRead($fh, @fileSize($lpszFileName));
    +		fclose($fh);
    +
    +		// GET FILE HEADER
    +		if (!$this->m_gfh->load($this->m_lpData, $len = 0)) {
    +			return false;
    +		}
    +		$this->m_lpData = substr($this->m_lpData, $len);
    +
    +		do {
    +			if (!$this->m_img->load($this->m_lpData, $imgLen = 0)) {
    +				return false;
    +			}
    +			$this->m_lpData = substr($this->m_lpData, $imgLen);
    +		}
    +		while ($iIndex-- > 0);
    +
    +		$this->m_bLoaded = true;
    +		return true;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function getSize($lpszFileName, &$width, &$height)
    +	{
    +		if (!($fh = @fopen($lpszFileName, 'rb'))) {
    +			return false;
    +		}
    +		$data = @fRead($fh, @fileSize($lpszFileName));
    +		@fclose($fh);
    +
    +		$gfh = new CGIFFILEHEADER();
    +		if (!$gfh->load($data, $len = 0)) {
    +			return false;
    +		}
    +
    +		$width  = $gfh->m_nWidth;
    +		$height = $gfh->m_nHeight;
    +		return true;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function getBmp($bgColor)
    +	{
    +		$out = '';
    +
    +		if (!$this->m_bLoaded) {
    +			return false;
    +		}
    +
    +		// PREPARE COLOR TABLE (RGBQUADs)
    +		if ($this->m_img->m_gih->m_bLocalClr) {
    +			$nColors = $this->m_img->m_gih->m_nTableSize;
    +			$rgbq    = $this->m_img->m_gih->m_colorTable->toRGBQuad();
    +			if ($bgColor != -1) {
    +				$bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor);
    +			}
    +		} elseif ($this->m_gfh->m_bGlobalClr) {
    +			$nColors = $this->m_gfh->m_nTableSize;
    +			$rgbq    = $this->m_gfh->m_colorTable->toRGBQuad();
    +			if ($bgColor != -1) {
    +				$bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor);
    +			}
    +		} else {
    +			$nColors =  0;
    +			$bgColor = -1;
    +		}
    +
    +		// PREPARE BITMAP BITS
    +		$data = $this->m_img->m_data;
    +		$nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth;
    +		$bmp  = '';
    +		$nPad = ($this->m_gfh->m_nWidth % 4) ? 4 - ($this->m_gfh->m_nWidth % 4) : 0;
    +		for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) {
    +			for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) {
    +				if (
    +					($x >= $this->m_img->m_gih->m_nLeft) &&
    +					($y >= $this->m_img->m_gih->m_nTop) &&
    +					($x <  ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) &&
    +					($y <  ($this->m_img->m_gih->m_nTop  + $this->m_img->m_gih->m_nHeight))) {
    +					// PART OF IMAGE
    +					if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) {
    +						// TRANSPARENT -> BACKGROUND
    +						if ($bgColor == -1) {
    +							$bmp .= chr($this->m_gfh->m_nBgColor);
    +						} else {
    +							$bmp .= chr($bgColor);
    +						}
    +					} else {
    +						$bmp .= $data{$nPxl};
    +					}
    +				} else {
    +					// BACKGROUND
    +					if ($bgColor == -1) {
    +						$bmp .= chr($this->m_gfh->m_nBgColor);
    +					} else {
    +						$bmp .= chr($bgColor);
    +					}
    +				}
    +			}
    +			$nPxl -= $this->m_gfh->m_nWidth << 1;
    +
    +			// ADD PADDING
    +			for ($x = 0; $x < $nPad; $x++) {
    +				$bmp .= "\x00";
    +			}
    +		}
    +
    +		// BITMAPFILEHEADER
    +		$out .= 'BM';
    +		$out .= $this->dword(14 + 40 + ($nColors << 2) + strlen($bmp));
    +		$out .= "\x00\x00";
    +		$out .= "\x00\x00";
    +		$out .= $this->dword(14 + 40 + ($nColors << 2));
    +
    +		// BITMAPINFOHEADER
    +		$out .= $this->dword(40);
    +		$out .= $this->dword($this->m_gfh->m_nWidth);
    +		$out .= $this->dword($this->m_gfh->m_nHeight);
    +		$out .= "\x01\x00";
    +		$out .= "\x08\x00";
    +		$out .= "\x00\x00\x00\x00";
    +		$out .= "\x00\x00\x00\x00";
    +		$out .= "\x12\x0B\x00\x00";
    +		$out .= "\x12\x0B\x00\x00";
    +		$out .= $this->dword($nColors % 256);
    +		$out .= "\x00\x00\x00\x00";
    +
    +		// COLOR TABLE
    +		if ($nColors > 0) {
    +			$out .= $rgbq;
    +		}
    +
    +		// DATA
    +		$out .= $bmp;
    +
    +		return $out;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function getPng($bgColor)
    +	{
    +		$out = '';
    +
    +		if (!$this->m_bLoaded) {
    +			return false;
    +		}
    +
    +		// PREPARE COLOR TABLE (RGBQUADs)
    +		if ($this->m_img->m_gih->m_bLocalClr) {
    +			$nColors = $this->m_img->m_gih->m_nTableSize;
    +			$pal     = $this->m_img->m_gih->m_colorTable->toString();
    +			if ($bgColor != -1) {
    +				$bgColor = $this->m_img->m_gih->m_colorTable->colorIndex($bgColor);
    +			}
    +		} elseif ($this->m_gfh->m_bGlobalClr) {
    +			$nColors = $this->m_gfh->m_nTableSize;
    +			$pal     = $this->m_gfh->m_colorTable->toString();
    +			if ($bgColor != -1) {
    +				$bgColor = $this->m_gfh->m_colorTable->colorIndex($bgColor);
    +			}
    +		} else {
    +			$nColors =  0;
    +			$bgColor = -1;
    +		}
    +
    +		// PREPARE BITMAP BITS
    +		$data = $this->m_img->m_data;
    +		$nPxl = 0;
    +		$bmp  = '';
    +		for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) {
    +			$bmp .= "\x00";
    +			for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) {
    +				if (
    +					($x >= $this->m_img->m_gih->m_nLeft) &&
    +					($y >= $this->m_img->m_gih->m_nTop) &&
    +					($x <  ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) &&
    +					($y <  ($this->m_img->m_gih->m_nTop  + $this->m_img->m_gih->m_nHeight))) {
    +					// PART OF IMAGE
    +					$bmp .= $data{$nPxl};
    +				} else {
    +					// BACKGROUND
    +					if ($bgColor == -1) {
    +						$bmp .= chr($this->m_gfh->m_nBgColor);
    +					} else {
    +						$bmp .= chr($bgColor);
    +					}
    +				}
    +			}
    +		}
    +		$bmp = gzcompress($bmp, 9);
    +
    +		///////////////////////////////////////////////////////////////////////
    +		// SIGNATURE
    +		$out .= "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
    +		///////////////////////////////////////////////////////////////////////
    +		// HEADER
    +		$out .= "\x00\x00\x00\x0D";
    +		$tmp  = 'IHDR';
    +		$tmp .= $this->ndword($this->m_gfh->m_nWidth);
    +		$tmp .= $this->ndword($this->m_gfh->m_nHeight);
    +		$tmp .= "\x08\x03\x00\x00\x00";
    +		$out .= $tmp;
    +		$out .= $this->ndword(crc32($tmp));
    +		///////////////////////////////////////////////////////////////////////
    +		// PALETTE
    +		if ($nColors > 0) {
    +			$out .= $this->ndword($nColors * 3);
    +			$tmp  = 'PLTE';
    +			$tmp .= $pal;
    +			$out .= $tmp;
    +			$out .= $this->ndword(crc32($tmp));
    +		}
    +		///////////////////////////////////////////////////////////////////////
    +		// TRANSPARENCY
    +		if (@$this->m_img->m_bTrans && ($nColors > 0)) {
    +			$out .= $this->ndword($nColors);
    +			$tmp  = 'tRNS';
    +			for ($i = 0; $i < $nColors; $i++) {
    +				$tmp .= ($i == $this->m_img->m_nTrans) ? "\x00" : "\xFF";
    +			}
    +			$out .= $tmp;
    +			$out .= $this->ndword(crc32($tmp));
    +		}
    +		///////////////////////////////////////////////////////////////////////
    +		// DATA BITS
    +		$out .= $this->ndword(strlen($bmp));
    +		$tmp  = 'IDAT';
    +		$tmp .= $bmp;
    +		$out .= $tmp;
    +		$out .= $this->ndword(crc32($tmp));
    +		///////////////////////////////////////////////////////////////////////
    +		// END OF FILE
    +		$out .= "\x00\x00\x00\x00IEND\xAE\x42\x60\x82";
    +
    +		return $out;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	// Added by James Heinrich  - January 5, 2003
    +
    +	// Takes raw image data and plots it pixel-by-pixel on a new GD image and returns that
    +	// It's extremely slow, but the only solution when ImageCreateFromString() fails
    +	function getGD_PixelPlotterVersion()
    +	{
    +		if (!$this->m_bLoaded) {
    +			return false;
    +		}
    +
    +		// PREPARE COLOR TABLE (RGBQUADs)
    +		if ($this->m_img->m_gih->m_bLocalClr) {
    +			$pal = $this->m_img->m_gih->m_colorTable->toString();
    +		} elseif ($this->m_gfh->m_bGlobalClr) {
    +			$pal = $this->m_gfh->m_colorTable->toString();
    +		} else {
    +			die('No color table available in getGD_PixelPlotterVersion()');
    +		}
    +
    +		$PlottingIMG = ImageCreate($this->m_gfh->m_nWidth, $this->m_gfh->m_nHeight);
    +		$NumColorsInPal = floor(strlen($pal) / 3);
    +		for ($i = 0; $i < $NumColorsInPal; $i++) {
    +			$ThisImageColor[$i] = ImageColorAllocate(
    +									$PlottingIMG,
    +									ord($pal{(($i * 3) + 0)}),
    +									ord($pal{(($i * 3) + 1)}),
    +									ord($pal{(($i * 3) + 2)}));
    +		}
    +
    +		// PREPARE BITMAP BITS
    +		$data = $this->m_img->m_data;
    +		$nPxl = ($this->m_gfh->m_nHeight - 1) * $this->m_gfh->m_nWidth;
    +		for ($y = 0; $y < $this->m_gfh->m_nHeight; $y++) {
    +			set_time_limit(30);
    +			for ($x = 0; $x < $this->m_gfh->m_nWidth; $x++, $nPxl++) {
    +				if (
    +					($x >= $this->m_img->m_gih->m_nLeft) &&
    +					($y >= $this->m_img->m_gih->m_nTop) &&
    +					($x <  ($this->m_img->m_gih->m_nLeft + $this->m_img->m_gih->m_nWidth)) &&
    +					($y <  ($this->m_img->m_gih->m_nTop  + $this->m_img->m_gih->m_nHeight))) {
    +					// PART OF IMAGE
    +					if (@$this->m_img->m_bTrans && (ord($data{$nPxl}) == $this->m_img->m_nTrans)) {
    +						ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]);
    +					} else {
    +						ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[ord($data{$nPxl})]);
    +					}
    +				} else {
    +					// BACKGROUND
    +					ImageSetPixel($PlottingIMG, $x, $this->m_gfh->m_nHeight - $y - 1, $ThisImageColor[$this->m_gfh->m_nBgColor]);
    +				}
    +			}
    +			$nPxl -= $this->m_gfh->m_nWidth << 1;
    +
    +		}
    +
    +		return $PlottingIMG;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function dword($val)
    +	{
    +		$val = intval($val);
    +		return chr($val & 0xFF).chr(($val & 0xFF00) >> 8).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF000000) >> 24);
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function ndword($val)
    +	{
    +		$val = intval($val);
    +		return chr(($val & 0xFF000000) >> 24).chr(($val & 0xFF0000) >> 16).chr(($val & 0xFF00) >> 8).chr($val & 0xFF);
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function width()
    +	{
    +		return $this->m_gfh->m_nWidth;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function height()
    +	{
    +		return $this->m_gfh->m_nHeight;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function comment()
    +	{
    +		return $this->m_img->m_lpComm;
    +	}
    +
    +	///////////////////////////////////////////////////////////////////////////
    +
    +	function loaded()
    +	{
    +		return $this->m_bLoaded;
    +	}
    +}
    +
    +///////////////////////////////////////////////////////////////////////////////////////////////////
    +
    +?>
    \ No newline at end of file
    diff --git a/common/phpThumb/phpthumb.ico.php b/common/phpThumb/phpthumb.ico.php
    new file mode 100644
    index 0000000..008021a
    --- /dev/null
    +++ b/common/phpThumb/phpthumb.ico.php
    @@ -0,0 +1,119 @@
    +   //
    +//        available at http://phpthumb.sourceforge.net     ///
    +//////////////////////////////////////////////////////////////
    +///                                                         //
    +// phpthumb.ico.php - .ICO output format functions          //
    +//                                                         ///
    +//////////////////////////////////////////////////////////////
    +
    +
    +class phpthumb_ico {
    +
    +	function phpthumb_ico() {
    +		return true;
    +	}
    +
    +
    +	function GD2ICOstring(&$gd_image_array) {
    +		foreach ($gd_image_array as $key => $gd_image) {
    +
    +			$ImageWidths[$key]  = ImageSX($gd_image);
    +			$ImageHeights[$key] = ImageSY($gd_image);
    +	    	$bpp[$key]          = ImageIsTrueColor($gd_image) ? 32 : 24;
    +	    	$totalcolors[$key]  = ImageColorsTotal($gd_image);
    +
    +			$icXOR[$key] = '';
    +			for ($y = $ImageHeights[$key] - 1; $y >= 0; $y--) {
    +				for ($x = 0; $x < $ImageWidths[$key]; $x++) {
    +					$argb = phpthumb_functions::GetPixelColor($gd_image, $x, $y);
    +					$a = round(255 * ((127 - $argb['alpha']) / 127));
    +					$r = $argb['red'];
    +					$g = $argb['green'];
    +					$b = $argb['blue'];
    +
    +					if ($bpp[$key] == 32) {
    +						$icXOR[$key] .= chr($b).chr($g).chr($r).chr($a);
    +					} elseif ($bpp[$key] == 24) {
    +						$icXOR[$key] .= chr($b).chr($g).chr($r);
    +					}
    +
    +					if ($a < 128) {
    +						@$icANDmask[$key][$y] .= '1';
    +					} else {
    +						@$icANDmask[$key][$y] .= '0';
    +					}
    +				}
    +				// mask bits are 32-bit aligned per scanline
    +				while (strlen($icANDmask[$key][$y]) % 32) {
    +					$icANDmask[$key][$y] .= '0';
    +				}
    +			}
    +			$icAND[$key] = '';
    +			foreach ($icANDmask[$key] as $y => $scanlinemaskbits) {
    +				for ($i = 0; $i < strlen($scanlinemaskbits); $i += 8) {
    +					$icAND[$key] .= chr(bindec(str_pad(substr($scanlinemaskbits, $i, 8), 8, '0', STR_PAD_LEFT)));
    +				}
    +			}
    +
    +		}
    +
    +	    foreach ($gd_image_array as $key => $gd_image) {
    +			$biSizeImage = $ImageWidths[$key] * $ImageHeights[$key] * ($bpp[$key] / 8);
    +
    +	    	// BITMAPINFOHEADER - 40 bytes
    +			$BitmapInfoHeader[$key]  = '';
    +			$BitmapInfoHeader[$key] .= "\x28\x00\x00\x00";                              // DWORD  biSize;
    +			$BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageWidths[$key], 4);      // LONG   biWidth;
    +			// The biHeight member specifies the combined
    +			// height of the XOR and AND masks.
    +			$BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($ImageHeights[$key] * 2, 4); // LONG   biHeight;
    +	    	$BitmapInfoHeader[$key] .= "\x01\x00";                                      // WORD   biPlanes;
    +	   		$BitmapInfoHeader[$key] .= chr($bpp[$key])."\x00";                          // wBitCount;
    +			$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                              // DWORD  biCompression;
    +			$BitmapInfoHeader[$key] .= phpthumb_functions::LittleEndian2String($biSizeImage, 4);            // DWORD  biSizeImage;
    +	    	$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                              // LONG   biXPelsPerMeter;
    +	    	$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                              // LONG   biYPelsPerMeter;
    +	    	$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                              // DWORD  biClrUsed;
    +	    	$BitmapInfoHeader[$key] .= "\x00\x00\x00\x00";                              // DWORD  biClrImportant;
    +		}
    +
    +
    +		$icondata  = "\x00\x00";                                      // idReserved;   // Reserved (must be 0)
    +		$icondata .= "\x01\x00";                                      // idType;       // Resource Type (1 for icons)
    +		$icondata .= phpthumb_functions::LittleEndian2String(count($gd_image_array), 2);  // idCount;      // How many images?
    +
    +		$dwImageOffset = 6 + (count($gd_image_array) * 16);
    +		foreach ($gd_image_array as $key => $gd_image) {
    +	    	// ICONDIRENTRY   idEntries[1]; // An entry for each image (idCount of 'em)
    +
    +	    	$icondata .= chr($ImageWidths[$key]);                     // bWidth;          // Width, in pixels, of the image
    +	    	$icondata .= chr($ImageHeights[$key]);                    // bHeight;         // Height, in pixels, of the image
    +	    	$icondata .= chr($totalcolors[$key]);                     // bColorCount;     // Number of colors in image (0 if >=8bpp)
    +	    	$icondata .= "\x00";                                      // bReserved;       // Reserved ( must be 0)
    +
    +	    	$icondata .= "\x01\x00";                                  // wPlanes;         // Color Planes
    +			$icondata .= chr($bpp[$key])."\x00";                      // wBitCount;       // Bits per pixel
    +
    +			$dwBytesInRes = 40 + strlen($icXOR[$key]) + strlen($icAND[$key]);
    +			$icondata .= phpthumb_functions::LittleEndian2String($dwBytesInRes, 4);       // dwBytesInRes;    // How many bytes in this resource?
    +
    +		    $icondata .= phpthumb_functions::LittleEndian2String($dwImageOffset, 4);      // dwImageOffset;   // Where in the file is this image?
    +			$dwImageOffset += strlen($BitmapInfoHeader[$key]);
    +			$dwImageOffset += strlen($icXOR[$key]);
    +			$dwImageOffset += strlen($icAND[$key]);
    +	    }
    +
    +	    foreach ($gd_image_array as $key => $gd_image) {
    +			$icondata .= $BitmapInfoHeader[$key];
    +			$icondata .= $icXOR[$key];
    +			$icondata .= $icAND[$key];
    +	    }
    +
    +	    return $icondata;
    +	}
    +
    +}
    +
    +?>
    \ No newline at end of file
    diff --git a/common/phpThumb/phpthumb.unsharp.php b/common/phpThumb/phpthumb.unsharp.php
    new file mode 100644
    index 0000000..ff32838
    --- /dev/null
    +++ b/common/phpThumb/phpthumb.unsharp.php
    @@ -0,0 +1,162 @@
    +   //
    +//  for use in phpThumb() on 3 February 2003.               //
    +//                                                          //
    +//  phpThumb() is found at http://phpthumb.sourceforge.net ///
    +//////////////////////////////////////////////////////////////
    +
    +/*
    +WARNING! Due to a known bug in PHP 4.3.2 this script is not working well in this version.
    +The sharpened images get too dark. The bug is fixed in version 4.3.3.
    +
    +Unsharp masking is a traditional darkroom technique that has proven very suitable for
    +digital imaging. The principle of unsharp masking is to create a blurred copy of the image
    +and compare it to the underlying original. The difference in colour values
    +between the two images is greatest for the pixels near sharp edges. When this
    +difference is subtracted from the original image, the edges will be
    +accentuated.
    +
    +The Amount parameter simply says how much of the effect you want. 100 is 'normal'.
    +Radius is the radius of the blurring circle of the mask. 'Threshold' is the least
    +difference in colour values that is allowed between the original and the mask. In practice
    +this means that low-contrast areas of the picture are left unrendered whereas edges
    +are treated normally. This is good for pictures of e.g. skin or blue skies.
    +
    +Any suggenstions for improvement of the algorithm, expecially regarding the speed
    +and the roundoff errors in the Gaussian blur process, are welcome.
    +*/
    +
    +class phpUnsharpMask {
    +
    +	function applyUnsharpMask(&$img, $amount, $radius, $threshold) {
    +
    +		// $img is an image that is already created within php using
    +		// imgcreatetruecolor. No url! $img must be a truecolor image.
    +
    +		// Attempt to calibrate the parameters to Photoshop:
    +		$amount = min($amount, 500);
    +		$amount = $amount * 0.016;
    +		if ($amount == 0) {
    +			return true;
    +		}
    +
    +		$radius = min($radius, 50);
    +		$radius = $radius * 2;
    +
    +		$threshold = min($threshold, 255);
    +
    +		$radius = abs(round($radius)); 	// Only integers make sense.
    +		if ($radius == 0) {
    +			return true;
    +		}
    +
    +		$w = ImageSX($img);
    +		$h = ImageSY($img);
    +		$imgCanvas  = ImageCreateTrueColor($w, $h);
    +		$imgCanvas2 = ImageCreateTrueColor($w, $h);
    +		ImageCopy($imgCanvas,  $img, 0, 0, 0, 0, $w, $h);
    +		ImageCopy($imgCanvas2, $img, 0, 0, 0, 0, $w, $h);
    +
    +
    +		$builtinFilterSucceeded = false;
    +		if ($radius == 1) {
    +			if (phpthumb_functions::version_compare_replacement(phpversion(), '5.0.0', '>=') && phpthumb_functions::gd_is_bundled()) {
    +				if (ImageFilter($imgCanvas, IMG_FILTER_GAUSSIAN_BLUR) && ImageFilter($imgCanvas2, IMG_FILTER_GAUSSIAN_BLUR)) {
    +					$builtinFilterSucceeded = true;
    +				}
    +			}
    +		}
    +
    +		if (!$builtinFilterSucceeded) {
    +			$imgBlur  = ImageCreateTrueColor($w, $h);
    +			$imgBlur2 = ImageCreateTrueColor($w, $h);
    +
    +			///////////////////////////
    +			//
    +			// Gaussian blur matrix:
    +			//	1  2  1
    +			//	2  4  2
    +			//	1  2  1
    +			//
    +			///////////////////////////
    +
    +			// Move copies of the image around one pixel at the time and merge them with weight
    +			// according to the matrix. The same matrix is simply repeated for higher radii.
    +			for ($i = 0; $i < $radius; $i++)	{
    +				ImageCopy     ($imgBlur, $imgCanvas, 0, 0, 1, 1, $w - 1, $h - 1);            // up left
    +				ImageCopyMerge($imgBlur, $imgCanvas, 1, 1, 0, 0, $w,     $h,     50);        // down right
    +				ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 1, 0, $w - 1, $h,     33.33333);  // down left
    +				ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 1, $w,     $h - 1, 25);        // up right
    +				ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 1, 0, $w - 1, $h,     33.33333);  // left
    +				ImageCopyMerge($imgBlur, $imgCanvas, 1, 0, 0, 0, $w,     $h,     25);        // right
    +				ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 1, $w,     $h - 1, 20 );       // up
    +				ImageCopyMerge($imgBlur, $imgCanvas, 0, 1, 0, 0, $w,     $h,     16.666667); // down
    +				ImageCopyMerge($imgBlur, $imgCanvas, 0, 0, 0, 0, $w,     $h,     50);        // center
    +				ImageCopy     ($imgCanvas, $imgBlur, 0, 0, 0, 0, $w,     $h);
    +
    +				// During the loop above the blurred copy darkens, possibly due to a roundoff
    +				// error. Therefore the sharp picture has to go through the same loop to
    +				// produce a similar image for comparison. This is not a good thing, as processing
    +				// time increases heavily.
    +				ImageCopy     ($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h);
    +				ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50);
    +				ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333);
    +				ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25);
    +				ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 33.33333);
    +				ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 25);
    +				ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 20 );
    +				ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 16.666667);
    +				ImageCopyMerge($imgBlur2, $imgCanvas2, 0, 0, 0, 0, $w, $h, 50);
    +				ImageCopy     ($imgCanvas2, $imgBlur2, 0, 0, 0, 0, $w, $h);
    +			}
    +			ImageDestroy($imgBlur);
    +			ImageDestroy($imgBlur2);
    +		}
    +
    +		// Calculate the difference between the blurred pixels and the original
    +		// and set the pixels
    +		for ($x = 0; $x < $w; $x++)	{ // each row
    +			for ($y = 0; $y < $h; $y++)	{ // each pixel
    +
    +				$rgbOrig = ImageColorAt($imgCanvas2, $x, $y);
    +				$rOrig = (($rgbOrig >> 16) & 0xFF);
    +				$gOrig = (($rgbOrig >>  8) & 0xFF);
    +				$bOrig =  ($rgbOrig        & 0xFF);
    +
    +				$rgbBlur = ImageColorAt($imgCanvas, $x, $y);
    +				$rBlur = (($rgbBlur >> 16) & 0xFF);
    +				$gBlur = (($rgbBlur >>  8) & 0xFF);
    +				$bBlur =  ($rgbBlur        & 0xFF);
    +
    +				// When the masked pixels differ less from the original
    +				// than the threshold specifies, they are set to their original value.
    +				$rNew = (abs($rOrig - $rBlur) >= $threshold) ? max(0, min(255, ($amount * ($rOrig - $rBlur)) + $rOrig)) : $rOrig;
    +				$gNew = (abs($gOrig - $gBlur) >= $threshold) ? max(0, min(255, ($amount * ($gOrig - $gBlur)) + $gOrig)) : $gOrig;
    +				$bNew = (abs($bOrig - $bBlur) >= $threshold) ? max(0, min(255, ($amount * ($bOrig - $bBlur)) + $bOrig)) : $bOrig;
    +
    +				if (($rOrig != $rNew) || ($gOrig != $gNew) || ($bOrig != $bNew)) {
    +					$pixCol = ImageColorAllocate($img, $rNew, $gNew, $bNew);
    +					ImageSetPixel($img, $x, $y, $pixCol);
    +				}
    +			}
    +		}
    +		ImageDestroy($imgCanvas);
    +		ImageDestroy($imgCanvas2);
    +
    +		return true;
    +	}
    +
    +}
    +
    +?>
    \ No newline at end of file
    diff --git a/common/php_writeexcel/class.ole.php b/common/php_writeexcel/class.ole.php
    new file mode 100644
    index 0000000..e69de29
    diff --git a/common/popup.php b/common/popup.php
    new file mode 100644
    index 0000000..84d9be3
    --- /dev/null
    +++ b/common/popup.php
    @@ -0,0 +1,79 @@
    + get_main_popup($language,$branch);
    +?>
    +
    +
    + 0){
    +		for($i=0;$i
    +
    +
    +
    +
    +
      
    + +
    +
    +
    + diff --git a/company_01.html b/company_01.html new file mode 100644 index 0000000..629ff7c --- /dev/null +++ b/company_01.html @@ -0,0 +1,187 @@ + + + + +
    +

    Start of Content

    + +
    + + +
    +
    +
      +
    • COMPANY
    • +
    • 끊임없이 변화와 혁신을 추구하는 기업 디비엔텍입니다
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 회사소개 +
    +
    + +
    + +

    >

    + +
      +
    • + 안녕하십니까? 미래가치를 창조하는 가치혁신 선도기업 주식회사 디비엔텍입니다. +
    • +
    • + 디비엔텍은 2018년 1월 5일 설립되었으며 Deep-learning과 Big-Data 기술에 기반한 차세대 + 기술 및 이동객체 영상분석솔루션
      개발 전문기업입니다. + 디비엔텍은 공공 SOC(Social Overhead Capital)에 설치되어 수집되는 방대한 CCTV영상 + 빅데이터의 분석 및 실시간 연계를 통하여 국민의 안전과 시설물관리 및 지능정보화구현을 + 위한 기술정보서비스제공을 주요 목적사업으로 수행하고 있습니다.
      + 디비엔텍은 제4차 산업혁명시대에 핵심기술인 인공지능을 활용한 지능정보화기술의 개발과 + 현장적용을 통하여 보다 안전하고 편리한 세상을 만드는데 기여하고자 하며 인간 삶의 + 향상을 추구하는 인간중심의 Human Technology 기업으로서의 역할을 다하고자합니다.
      + 주식회사 디비엔텍 임직원 일동 +
    • +
    + +
    +
    +
      +
    • +
      +
      디비엔텍 로고
      +
      Deeplearning BigData Next Technology
      +
      주식회사 디비엔텍
      +
      +
    • +
    + +
      +
    • +
      +
      주 소
      +
      설 립 일 자
      +
      사 업 분 야
      +
      인 증 현 황
      +
      대 표 전 화
      +
      팩 스
      +
      사 업 문 의
      +
      +
    • +
    • +
      +
      인천광역시 서구 로봇랜드로 155-11 로봇타워 1205호
      +
      2018년 01월 05일
      +
      인공지능, 영상 빅데이터, Smart SOC, IT Service
      +
      중소기업확인서 / 여성기업확인서 / 기업부설연구소 취득 / 벤처기업확인서
      +
      032-721-5670
      +
      032-721-5680
      +
      ahn@dbnt.co.kr
      +
      +
    • +
    +
    +
    +
    + +
    + +

    조직도

    + +
    + + + + + +
    + + + + + + \ No newline at end of file diff --git a/company_02.html b/company_02.html new file mode 100644 index 0000000..99b8c68 --- /dev/null +++ b/company_02.html @@ -0,0 +1,382 @@ + + + + +
    +

    Start of Content

    + +
    + + + +
    +
    +
      +
    • COMPANY
    • +
    • 끊임없이 변화와 혁신을 추구하는 기업 디비엔텍입니다
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 주요연혁 +
    +
    + +
    + + +
      +
    1. <
    2. +
    3. >
    4. +
    + +

    주요연혁

    + +
    +
    +

    2020

    +
      +
    • +
      +
      +
        +
      • 05월.
      • +
      • 2020년 재도전성공패키지사업 지원대상자 최종선정(창업진흥원)
      • +
      +
      +
      +
        +
      • 05월.
      • +
      • 2020년 글로벌 맞춤형 지원사업 지원대상자 최종선정(인천테크노파크)
      • +
      +
      +
      +
        +
      • 05월.
      • +
      • KICT(3D GIS기술지반증폭 GIS분석맵 및 LPI_LSN기반 액상화위험지도 구축 프로그램 개발 3차) 수주
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 04월.
      • +
      • 2020년 상반기 IP나래 프로그램 신청과제 최종선정(인천지식재산센터)
      • +
      +
      +
      +
        +
      • 04월.
      • +
      • 국내외 전시회 개별참가 지원사업 지원대상자 최종선정(인천테크노파크)
      • +
      +
      +
      +
        +
      • 04월.
      • +
      • 국토교통부 연구과제(모바일 기반 지반공간통합지도 현장활용지원 통합관리기술개발 1차) 수주
      • +
      +
      +
      +
        +
      • 04월.
      • +
      • AI바우처 지원사업 공급기업 선정(정보통신산업진흥원)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 03월.
      • +
      • KICT 위탁과제(딥러닝 기반 영상 간 실시간 객체/영역 인식 및 매칭시스템 통합소프트웨어 개발과 취득
        영상 데이터 가공 3차) 수주
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 02월.
      • +
      • 해양경찰청 국제해양정보시스템 유지관리 용역 계약
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 01월.
      • +
      • 해양경찰청 사이버외사시스템 유지관리 용역 계약
      • +
      +
      +
      +
    • +
    +
    +
    +

    2019

    +
      +
    • +
      +
      +
        +
      • 12월.
      • +
      • TADs 시스템 구축 : 충북도로관리사업소 덕천 터널
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 11월.
      • +
      • 연구개발서비스업 등록 (제20192625호)
      • +
      +
      +
      +
        +
      • 11월.
      • +
      • 혁신형 창업 과제
        (딥러닝 기반 주·야간 돌발상황 관제 지원 시스템 및 관제요원 주도 성장형 관제 모듈의 개발) 수주
      • +
      +
      +
      +
        +
      • 11월.
      • +
      • 2019 스마트 건설기술·안전 박람회 참가 (with KCC건설)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 09월.
      • +
      • 2019 국제도로교통박람회 참가
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 08월.
      • +
      • 연구시설 추가 확보를 위한 사옥 이전 (인천광역시 서구 로봇랜드로 155-11 로봇타워 905호, 906호)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 07월.
      • +
      • KICT 연구과제 (지반증폭 GIS 분석맵 및 LPI_LSN 기반 액상화 위험지도 구축 프로그램 개발)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 06월.
      • +
      • TADs 시스템 시범 서비스 개시 : 충주국토관리사무소 다릿재터널
        *TADs(Tunnel Accident Detection system)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 03월.
      • +
      • KICT 연구과제(달 현지 영상내 주요 객체 자동인식 및 관심영역 자동 분류를 위한 딥러닝 코드 작성 및
        학습용 영상 레이블링 작업)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 02월.
      • +
      • 기업부설연구소 인증취득(제 2019110685 호)
      • +
      +
      +
      +
        +
      • 02월.
      • +
      • 프로그램 등록 (특징값 증강 알고리즘을 통한 객체인식 딥러닝 모델 추론 성능 향상 시스템)
      • +
      +
      +
      +
    • +
    +
    +
    +

    2018

    +
      +
    • +
      +
      +
        +
      • 11월.
      • +
      • + 한국건설기술연구원(KICT)와 패밀리기업 체결 +
      • +
      +
      +
      +
        +
      • 11월.
      • +
      • 한국건설기술연구원(KICT)와 기술이전 협약
      • +
      +
      +
      +
        +
      • 11월.
      • +
      • 창업성장 기술개발 사업
        (열악조건 CCTV 영상에 대한 교통류 돌발상황 자동인지 성능 향상 기술개발)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 07월.
      • +
      • 연구시설 확보를 위한 사옥 이전 (18.07.29 인천광역시 서구 로봇랜드로 155-11 로봇타워)
      • +
      +
      +
      +
        +
      • 07월.
      • +
      • 벤처기업 인증 취득(제20180401697호)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • + 06월. +
      • +
      • + 2018년 선도벤처연계창업지원사업 지원대상자 선정 +
      • +
      +
      +
      +
        +
      • 06월.
      • +
      • 기술평가대출기업-중소기업진흥공단 재도약지원자금 확정
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 05월.
      • +
      • + KICT 연구과제(달 지상 이미지 객체 인식을 위한 딥러닝 코드 작성 및 영상 처리 빅데이터 구축) +
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 03월.
      • +
      • + 프로그램등록(기계학습 기반 빅데이터 분석시스템) +
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 02월.
      • +
      • + 여성기업확인 인증 취득(인천지방중소벤처기업청 : 제0116-2018-01732호) +
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 01월.
      • +
      • 법인설립, 주식회사 디비엔텍 설립(법인등록 : 120111 -0914970)
      • +
      + +
      +
      +
        +
      • 01월.
      • +
      • 사업자등록 (북인천세무서 : 704 - 88 - 00959)
      • +
      +
      +
      +
        +
      • 01월.
      • +
      • 중소기업확인 인증 (중소기업청 : 0010 - 2018 -0001954)
      • +
      +
      +
      +
        +
      • 01월.
      • +
      • 소프트웨어 사업자 신고 (한국소프트웨어산업협회 : B18 - 160654)
      • +
      +
      +
      +
        +
      • 01월.
      • +
      • 직접생산증명 취득 (중소기업중앙회 : 제2018 - 0071 - 03760)
      • +
      +
      +
      +
        +
      • 01월.
      • +
      • 국가를 상대로 한 공공입찰 참가자격 등록
      • +
      +
      +
      +
        +
      • 01월.
      • +
      • 연구개발 전담부서 인증 취득 (한국산업기술흥협회 : 제 2018150584)
      • +
      +
      +
      +
    • +
    +
    +
    +
    +
    + + + + + \ No newline at end of file diff --git a/company_03.html b/company_03.html new file mode 100644 index 0000000..c950305 --- /dev/null +++ b/company_03.html @@ -0,0 +1,128 @@ + + + + +
    +

    Start of Content

    +
    + + + +
    +
    +
      +
    • COMPANY
    • +
    • 끊임없이 변화와 혁신을 추구하는 기업 디비엔텍입니다
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 인증현황 +
    +
    +
    + +

    <

    + +
    +
      +
    • + 인증현황 +
    • +
    +
    +
    +
      +
    • +
      +
      벤처기업확인서 사진
      +
      벤처기업확인서
      +
      +
    • +
    • +
      +
      기업부설연구소 사진
      +
      기업부설연구소 인정서
      +
      +
    • +
    • +
      +
      SW사업자신고확인서 사진
      +
      SW사업자신고확인서
      + +
      +
    • +
    +
    +
    +
      +
    • +
      +
      직접생산확인증명서 사진
      +
      직접생산확인증명서
      +
      +
    • +
    • +
      +
      중소기업확인서 사진
      +
      중소기업확인서
      +
      +
    • +
    • +
      +
      경쟁입찰참가자격증등록 사진
      +
      경쟁입찰참가자격증등록
      +
      +
    • +
    +
    +
    +
      +
    • +
      +
      여성기업확인서 사진
      +
      여성기업확인서
      +
      +
    • +
    • +
      +
      프로그램등록증 사진
      +
      프로그램등록증
      +
      +
    • +
    • +
      +
      프로그램등록증 사진
      +
      프로그램등록증
      + +
      +
    • +
    +
    +
    +
      +
    • +
      +
      연구개발서비스업 신고증
      +
      연구개발서비스업 신고증
      +
      +
    • +
    +
    +
    + + +
    + + + +
    +
    + + + + + \ No newline at end of file diff --git a/company_04.html b/company_04.html new file mode 100644 index 0000000..c5bc43c --- /dev/null +++ b/company_04.html @@ -0,0 +1,139 @@ + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • COMPANY
    • +
    • 끊임없이 변화와 혁신을 추구하는 기업 디비엔텍입니다
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 인재채용 +
    +
    +
    + +
    +
      +
    • 인재
      채용
    • +
    • 디비엔텍은 창의적이고 전문성 있는
      인재를 찾습니다.
    • +
    +
    +
    +

    인재상

    +
      +
    • 늘 새로움을 추구하는 도전적인 분
    • +
    • 발상과 인식을 전환할 수 있는 분
    • +
    • 시도한 일에는 반드시 성과를 내는 집념과 열정을 갖춘 분
    • +
    • 맡은업무를 성실히 임하는 분
    • +
    • 팀원과 원활한 협업을 할 수 있는 분
    • +
    • 전문지식을 기반으로 스마트한 업무 능력을 갖춘 분
    • +
    + +
    +
    +

    채용분야

    + +
    +
      +
    • +
      +
      주식회사 디비엔텍
      +
      연구개발부
      +
      개발자/연구원
      +
      +
    • +
    • img
    • +
    +
      +
    • +
      +
      주식회사 디비엔텍
      +
      시스템개발본부
      +
      개발자/프로그래머
      +
      +
    • +
    • img
    • +
    +
    + +
    +

    X

    +
      +
    • +
      +
      개발/연구원
      +
      연구개발부
      +
      +
    • +
    • +
        +
      • 필요역량 및 우대조건
      • +
      • +
        +
        전공 : 공학계
        +
        학위 : 학사 이상
        +
        ■ Python, Deeplearning Framework(Tensorflow) 숙련자 (필수)
        +
        ■ 딥러닝 모델 디자인/구축 가능자(CNN, Object Detection 관련) (필수)
        +
        ■ 머신러닝 또는 딥러닝 기반의 알고리즘 개발 경력 1년이상 (우대)
        +
        ■ Kaggle등 오픈 데이터셋 분석 경험자 (우대)
        +
        ■ 정보처리기사 자격증 소지자 (우대)
        +
        +
      • +
      +
    • +
    +
      +
    • +
      +
      개발/프로그래머
      +
      시스템개발본부
      +
      +
    • +
    • +
        +
      • 필요역량 및 우대조건
      • +
      • +
        +
        전공 : 공학계
        +
        학위 : 전문학사 이상
        +
        ■ 개발부문 : ASP, Java, Spring, JSP, C, C⁺⁺, MFC
        +
        ■ 서버운영 부문 : Windows Server, Linux, IIS, Tomcat
        +
        ■ 데이터베이스 부문 : Oracle, MySql
        +
        +
      • +
      +
    • +
    + +
    +
    + +
    +

    기타

    +
      +
    • 채용시기 : 상시 모집
    • +
    • 채용절차 : 1차(서류) → 2차(면접) → 최종합격
    • +
    • 복리후생 : 각종 경조사 지원, 직무능력 향상 교육비 지원, 도서구입비 지원, 사내친목도모비 지원 등
    • +
    +
    + + +
    +
    + + + + + \ No newline at end of file diff --git a/contact_us.html b/contact_us.html new file mode 100644 index 0000000..da51f98 --- /dev/null +++ b/contact_us.html @@ -0,0 +1,65 @@ + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • CONTACT US
    • +
    • -
    • +
    +
    +
    +
    + +
    +
    + CONTACT US +
    +
    +
    + +

    contact us

    + +
    +
      + +
    • (주)디비엔텍
    • +
    • 22851 인천광역시 서구 로봇랜드로 155-11
      로봇타워 1205호
    • +
    • + ahn@dbnt.co.kr +
    • +
    • + 032)721.5670 +
    • +
    • + 032)721.5680 +
    • +
    +
    + +
    +
    +
    + +
    +
    + + + + + + + \ No newline at end of file diff --git a/css/.sass-cache/3ae9501fc484fba00f2b6601b3024ad6009bea53/business.scssc b/css/.sass-cache/3ae9501fc484fba00f2b6601b3024ad6009bea53/business.scssc new file mode 100644 index 0000000..c3ae12f Binary files /dev/null and b/css/.sass-cache/3ae9501fc484fba00f2b6601b3024ad6009bea53/business.scssc differ diff --git a/css/.sass-cache/3ae9501fc484fba00f2b6601b3024ad6009bea53/company.scssc b/css/.sass-cache/3ae9501fc484fba00f2b6601b3024ad6009bea53/company.scssc new file mode 100644 index 0000000..706627a Binary files /dev/null and b/css/.sass-cache/3ae9501fc484fba00f2b6601b3024ad6009bea53/company.scssc differ diff --git a/css/.sass-cache/3ae9501fc484fba00f2b6601b3024ad6009bea53/layout.scssc b/css/.sass-cache/3ae9501fc484fba00f2b6601b3024ad6009bea53/layout.scssc new file mode 100644 index 0000000..bffaceb Binary files /dev/null and b/css/.sass-cache/3ae9501fc484fba00f2b6601b3024ad6009bea53/layout.scssc differ diff --git a/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/business.scssc b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/business.scssc new file mode 100644 index 0000000..fe7dec3 Binary files /dev/null and b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/business.scssc differ diff --git a/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/color.scssc b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/color.scssc new file mode 100644 index 0000000..8875201 Binary files /dev/null and b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/color.scssc differ diff --git a/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/company.scssc b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/company.scssc new file mode 100644 index 0000000..8e0ae0e Binary files /dev/null and b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/company.scssc differ diff --git a/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/contact.scssc b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/contact.scssc new file mode 100644 index 0000000..d006caf Binary files /dev/null and b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/contact.scssc differ diff --git a/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/layout.scssc b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/layout.scssc new file mode 100644 index 0000000..2cb7ce5 Binary files /dev/null and b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/layout.scssc differ diff --git a/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/rnd.scssc b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/rnd.scssc new file mode 100644 index 0000000..a81bbce Binary files /dev/null and b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/rnd.scssc differ diff --git a/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/status.scssc b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/status.scssc new file mode 100644 index 0000000..2b8f170 Binary files /dev/null and b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/status.scssc differ diff --git a/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/style.scssc b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/style.scssc new file mode 100644 index 0000000..b238e28 Binary files /dev/null and b/css/.sass-cache/6fd589d4e741bbb535642a0be39e6bc5d3d6ecab/style.scssc differ diff --git a/css/.sass-cache/fed6eaad74e08ac428fe4056fd2e543f1fca7bbb/business.scssc b/css/.sass-cache/fed6eaad74e08ac428fe4056fd2e543f1fca7bbb/business.scssc new file mode 100644 index 0000000..1181e9c Binary files /dev/null and b/css/.sass-cache/fed6eaad74e08ac428fe4056fd2e543f1fca7bbb/business.scssc differ diff --git a/css/.sass-cache/fed6eaad74e08ac428fe4056fd2e543f1fca7bbb/contact.scssc b/css/.sass-cache/fed6eaad74e08ac428fe4056fd2e543f1fca7bbb/contact.scssc new file mode 100644 index 0000000..1484e3c Binary files /dev/null and b/css/.sass-cache/fed6eaad74e08ac428fe4056fd2e543f1fca7bbb/contact.scssc differ diff --git a/css/.sass-cache/fed6eaad74e08ac428fe4056fd2e543f1fca7bbb/layout.scssc b/css/.sass-cache/fed6eaad74e08ac428fe4056fd2e543f1fca7bbb/layout.scssc new file mode 100644 index 0000000..49ba26c Binary files /dev/null and b/css/.sass-cache/fed6eaad74e08ac428fe4056fd2e543f1fca7bbb/layout.scssc differ diff --git a/css/business.css b/css/business.css new file mode 100644 index 0000000..c5d4ae8 --- /dev/null +++ b/css/business.css @@ -0,0 +1,375 @@ +.subBanner { + width: 100%; + height: 200px; + background: url(../images/busi_2.jpg); + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; } + +em { + padding-left: 10px; } + +.innerIndex { + width: 100%; + margin: 0px auto 0; + background-color: #efefef; } + .innerIndex > ul > li { + float: left; + width: 33.333333%; + text-align: center; } + .innerIndex > ul > li > a { + display: block; + height: 40px; + line-height: 40px; + color: #555; + font-weight: 600; } + .innerIndex > ul > li > a:hover { + background-color: #bbb; + color: #fff; } + +.businessContainer { + margin: 0; } + .businessContainer > .aiWrapper { + width: 100%; + height: 500px; + background-image: url(../images/busi.jpg); + background-position: 0 100%; + background-repeat: no-repeat; + background-size: cover; } + .businessContainer > .aiWrapper > p { + display: none; + position: absolute; + top: 30px; + right: 30px; + z-index: 9999; } + .businessContainer > .aiWrapper > p > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .businessContainer > .aiWrapper > .aiRightBox { + position: relative; + width: 950px; + height: 100%; + background-color: #0061a9; } + .businessContainer > .aiWrapper > .aiRightBox:after { + position: absolute; + top: 40px; + right: 50px; + width: 300px; + height: 200px; + background-image: url(../images/ai_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; } + .businessContainer > .aiWrapper > .aiRightBox > ul { + padding-top: 220px; + margin-left: 350px; + margin-right: 80px; } + .businessContainer > .aiWrapper > .aiRightBox > ul > li { + position: relative; + list-style: disc; + font-size: 14px; + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; + /* + &:after { + position: absolute; + top: 50%; + left: -20px; + transform: translateY(-50%); + width: 5px; + height: 5px; + border-radius: 30px; + background-color: #fff; + content: ''; + } + */ } + .businessContainer > .aiWrapper > .aiRightBox > ul > li:first-child { + font-size: 30px; + font-weight: 600; + list-style: none; } + .businessContainer > .socWrapper { + width: 100%; + height: 500px; + background-image: url(../images/smart_b.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + .businessContainer > .socWrapper > ol { + display: none; + position: absolute; + top: 30px; + right: 20px; + z-index: 9999; } + .businessContainer > .socWrapper > ol > li { + float: left; } + .businessContainer > .socWrapper > ol > li > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .businessContainer > .socWrapper > .socRightBox { + position: relative; + width: 950px; + height: 100%; + background-color: #3a87ab; } + .businessContainer > .socWrapper > .socRightBox:after { + position: absolute; + top: 40px; + right: 50px; + width: 300px; + height: 200px; + background-image: url(../images/soc_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; } + .businessContainer > .socWrapper > .socRightBox > ul { + padding-top: 220px; + margin-left: 350px; + margin-right: 80px; } + .businessContainer > .socWrapper > .socRightBox > ul > li { + position: relative; + list-style: disc; + font-size: 14px; + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; } + .businessContainer > .socWrapper > .socRightBox > ul > li:first-child { + font-size: 30px; + font-weight: 600; + list-style: none; } + .businessContainer > .siWrapper { + width: 100%; + height: 500px; + background-image: url(../images/server_3.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + .businessContainer > .siWrapper > p { + display: none; } + .businessContainer > .siWrapper > .siRightBox { + position: relative; + width: 950px; + height: 100%; + background-color: #00a9a7; } + .businessContainer > .siWrapper > .siRightBox:after { + position: absolute; + top: 40px; + right: 80px; + width: 200px; + height: 200px; + background-image: url(../images/coding_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; } + .businessContainer > .siWrapper > .siRightBox > ul { + padding-top: 220px; + margin-left: 350px; + margin-right: 80px; } + .businessContainer > .siWrapper > .siRightBox > ul > li { + list-style: disc; + position: relative; + font-size: 14px; + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; } + .businessContainer > .siWrapper > .siRightBox > ul > li:first-child { + font-size: 30px; + font-weight: 600; + list-style: none; } + +@media screen and (max-width: 768px) { + .subBanner { + width: 100%; + height: 250px; + background: url(../images/busi_2_b.png); + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; } + + .businessContainer { + margin: 0; } + .businessContainer > .aiWrapper { + position: relative; + width: 100%; + height: auto; + background-image: url(../images/busi.jpg); + background-position: 0 100%; + background-repeat: no-repeat; + background-size: cover; } + .businessContainer > .aiWrapper > p { + display: block; + position: absolute; + top: 30px; + right: 30px; + z-index: 9999; } + .businessContainer > .aiWrapper > p > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .businessContainer > .aiWrapper > .aiRightBox { + position: relative; + width: 100%; + height: 100%; + background-color: #0061a9; + padding-bottom: 50px; } + .businessContainer > .aiWrapper > .aiRightBox:after { + position: absolute; + top: 100px; + right: 50%; + transform: translateX(50%); + width: 220px; + height: 150px; + background-image: url(../images/ai_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; } + .businessContainer > .aiWrapper > .aiRightBox > ul { + padding-top: 300px; + margin-left: 30px; + margin-right: 30px; } + .businessContainer > .aiWrapper > .aiRightBox > ul > li { + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; + font-size: 13px; } + .businessContainer > .aiWrapper > .aiRightBox > ul > li > br { + display: none; } + .businessContainer > .aiWrapper > .aiRightBox > ul > li > em { + padding-left: 0; } + .businessContainer > .aiWrapper > .aiRightBox > ul > li:first-child { + font-size: 30px; + font-weight: 600; } + .businessContainer > .socWrapper { + position: relative; + width: 100%; + height: auto; + background-image: url(../images/smart_b.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + .businessContainer > .socWrapper > ol { + display: block; + position: absolute; + top: 30px; + right: 20px; + z-index: 9999; } + .businessContainer > .socWrapper > ol > li { + float: left; } + .businessContainer > .socWrapper > ol > li > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .businessContainer > .socWrapper > .socRightBox { + position: relative; + width: 100%; + height: 100%; + background-color: #3a87ab; + padding-bottom: 50px; } + .businessContainer > .socWrapper > .socRightBox:after { + position: absolute; + top: 100px; + right: 50%; + transform: translateX(50%); + width: 220px; + height: 150px; + background-image: url(../images/soc_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; } + .businessContainer > .socWrapper > .socRightBox > ul { + padding-top: 300px; + margin-left: 30px; + margin-right: 30px; } + .businessContainer > .socWrapper > .socRightBox > ul > li { + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; + font-size: 13px; } + .businessContainer > .socWrapper > .socRightBox > ul > li > br { + display: none; } + .businessContainer > .socWrapper > .socRightBox > ul > li > em { + padding-left: 0; } + .businessContainer > .socWrapper > .socRightBox > ul > li:first-child { + font-size: 30px; + font-weight: 600; } + .businessContainer > .siWrapper { + position: relative; + width: 100%; + height: auto; + background-image: url(../images/si.jpg); + background-position: 0% 50%; + background-repeat: no-repeat; + background-size: cover; } + .businessContainer > .siWrapper > p { + display: block; + position: absolute; + top: 30px; + right: 30px; + z-index: 99999; } + .businessContainer > .siWrapper > p > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .businessContainer > .siWrapper > .siRightBox { + position: relative; + width: 100%; + height: 100%; + background-color: #00a9a7; + padding-bottom: 50px; } + .businessContainer > .siWrapper > .siRightBox:after { + position: absolute; + top: 100px; + right: 50%; + transform: translateX(50%); + width: 220px; + height: 150px; + background-image: url(../images/coding_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; + content: ''; } + .businessContainer > .siWrapper > .siRightBox > ul { + padding-top: 300px; + margin-left: 30px; + margin-right: 30px; } + .businessContainer > .siWrapper > .siRightBox > ul > li { + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; + font-size: 13px; } + .businessContainer > .siWrapper > .siRightBox > ul > li > br { + display: none; } + .businessContainer > .siWrapper > .siRightBox > ul > li > em { + padding-left: 0; } + .businessContainer > .siWrapper > .siRightBox > ul > li:first-child { + font-size: 30px; + font-weight: 600; } } + +/*# sourceMappingURL=business.css.map */ diff --git a/css/business.css.map b/css/business.css.map new file mode 100644 index 0000000..1b69a05 --- /dev/null +++ b/css/business.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["business.scss"], +"names": [], +"file": "business.css" +} \ No newline at end of file diff --git a/css/business.scss b/css/business.scss new file mode 100644 index 0000000..4254fe7 --- /dev/null +++ b/css/business.scss @@ -0,0 +1,627 @@ +.subBanner { + width: 100%; + height: 200px; + background: url(../images/busi_2.jpg) ; + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; + +}//end of subBanner + +em { + padding-left: 10px; +} + + + +.innerIndex { + width: 100%; + margin: 0px auto 0; + background-color: #efefef; + + >ul { + >li { + float: left; + width: 33.333333%; + text-align: center; + + + + >a { + display: block; + height: 40px; + line-height: 40px; + color: #555; + font-weight: 600; + + + + &:hover { + background-color: #bbb; + color: #fff; + } + + } + + + + } + } + +}//end of innerIndex + + +.businessContainer { + margin: 0; + + >.aiWrapper { + width: 100%; + height: 500px; + background-image: url(../images/busi.jpg); + background-position: 0 100%; + background-repeat: no-repeat; + background-size: cover; + + >p { + display: none; + position: absolute; + top: 30px; + right: 30px; + z-index: 9999; + + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + + } + + >.aiRightBox { + position: relative; + width: 950px; + height: 100%; + background-color: #0061a9; + + &:after { + position: absolute; + top: 40px; + right : 50px; + width: 300px; + height: 200px; + background-image: url(../images/ai_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; + } + + + + >ul { + padding-top: 220px; + margin-left: 350px; + margin-right: 80px; + + >li { + position: relative; + list-style: disc; + font-size: 14px; + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; +/* + &:after { + position: absolute; + top: 50%; + left: -20px; + transform: translateY(-50%); + width: 5px; + height: 5px; + border-radius: 30px; + background-color: #fff; + content: ''; + } + */ + + &:first-child { + font-size: 30px; + font-weight: 600; + list-style: none;; + + + + }//타이틀 + + + } + + }//end of ul + + }//end of aiRightBox + + + }//end of aiWrapper + + + + >.socWrapper { + width: 100%; + height: 500px; + background-image: url(../images/smart_b.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + + >ol { + display: none; + position: absolute; + top: 30px; + right: 20px; + z-index: 9999; + + >li { + float: left; + + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + } + + } + + >.socRightBox { + position: relative; + width: 950px; + height: 100%; + background-color: #3a87ab; + + &:after { + position: absolute; + top: 40px; + right : 50px; + width: 300px; + height: 200px; + background-image: url(../images/soc_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; + } + + + + >ul { + padding-top: 220px; + margin-left: 350px; + margin-right: 80px; + + >li { + position: relative; + list-style: disc; + font-size: 14px; + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; + + + + + &:first-child { + font-size: 30px; + font-weight: 600; + list-style: none; + + + }//타이틀 + + + } + + }//end of ul + + }//end of socRightBox + + + }//end of socWrapper + + + + + >.siWrapper { + width: 100%; + height: 500px; + background-image: url(../images/server_3.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + + >p { + display: none; + } + + >.siRightBox { + position: relative; + width: 950px; + height: 100%; + background-color: #00a9a7; + + &:after { + position: absolute; + top: 40px; + right : 80px; + width: 200px; + height: 200px; + background-image: url(../images/coding_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; + } + + + + >ul { + padding-top: 220px; + margin-left: 350px; + margin-right: 80px; + + >li { + list-style: disc; + position: relative; + font-size: 14px; + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; + + + + &:first-child { + font-size: 30px; + font-weight: 600; + list-style: none; + + + }//타이틀 + + + } + + }//end of ul + + }//end of socRightBox + + + }//end of socWrapper + +}//end of businessContainer + + + + + +@media screen and (max-width:768px) { + + .subBanner { + width: 100%; + height: 250px;//변경 + background: url(../images/busi_2_b.png) ; + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; + + }//end of subBanner + + .businessContainer { + margin: 0; + + + + + >.aiWrapper { + position: relative; + width: 100%; + height: auto; + background-image: url(../images/busi.jpg); + background-position: 0 100%; + background-repeat: no-repeat; + background-size: cover; + + >p { + display: block; + position: absolute; + top: 30px; + right: 30px; + z-index: 9999; + + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + + } + + >.aiRightBox { + position: relative; + width: 100%;//50% + height: 100%;//100% + background-color: #0061a9; + padding-bottom : 50px; + + &:after { + position: absolute; + top: 100px; + right : 50%; + transform: translateX(50%); + width: 220px;//420px + height: 150px;//300px + background-image: url(../images/ai_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; + } + + + + >ul { + padding-top: 300px;//330px + margin-left: 30px;//350px + margin-right: 30px;//80px + + >li { + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; + font-size: 13px; + + >br { + display: none; + } + + >em { + padding-left: 0; + + } + + + + + &:first-child { + font-size: 30px; + font-weight: 600; + + }//타이틀 + + + } + + }//end of ul + + }//end of aiRightBox + + + }//end of aiWrapper + + + + >.socWrapper { + position: relative; + width: 100%; + height: auto; + background-image: url(../images/smart_b.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + + >ol { + display: block; + position: absolute; + top: 30px; + right: 20px; + z-index: 9999; + + >li { + float: left; + + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + } + + } + + >.socRightBox { + position: relative; + width: 100%;//50% + height: 100%;//100% + background-color: #3a87ab; + padding-bottom : 50px; + + &:after { + position: absolute; + top: 100px; + right : 50%; + transform: translateX(50%); + width: 220px;//420px + height: 150px;//300px + background-image: url(../images/soc_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; + } + + + + >ul { + padding-top: 300px;//330px + margin-left: 30px;//350px + margin-right: 30px;//80px + + >li { + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; + font-size: 13px; + + >br { + display: none; + } + + >em { + padding-left: 0; + + } + + + + + &:first-child { + font-size: 30px; + font-weight: 600; + + }//타이틀 + + + } + + }//end of ul + + }//end of socRightBox + + + }//end of socWrapper + + + + + >.siWrapper { + position: relative; + width: 100%; + height: auto; + background-image: url(../images/si.jpg); + background-position: 0% 50%; + background-repeat: no-repeat; + background-size: cover; + + >p { + display: block; + position: absolute; + top: 30px; + right: 30px; + z-index: 99999; + + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + + } + + >.siRightBox { + position: relative; + width: 100%;//50% + height: 100%;//100% + background-color: #00a9a7; + padding-bottom : 50px; + + &:after { + position: absolute; + top: 100px; + right : 50%; + transform: translateX(50%); + width: 220px;//420px + height: 150px;//300px + background-image: url(../images/coding_c.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; + content: ''; + } + + + + >ul { + padding-top: 300px;//330px + margin-left: 30px;//350px + margin-right: 30px;//80px + + >li { + margin-bottom: 10px; + line-height: 1.7em; + color: #fff; + text-shadow: 1px 2px #000; + font-size: 13px; + + >br { + display: none; + } + + >em { + padding-left: 0; + + } + + + + + &:first-child { + font-size: 30px; + font-weight: 600; + + }//타이틀 + + + } + + }//end of ul + + }//end of socRightBox + + + }//end of socWrapper + + }//end of businessContainer +}//end of mediaQuery \ No newline at end of file diff --git a/css/color.css b/css/color.css new file mode 100644 index 0000000..8b78176 --- /dev/null +++ b/css/color.css @@ -0,0 +1,3 @@ + + +/*# sourceMappingURL=color.css.map */ diff --git a/css/color.css.map b/css/color.css.map new file mode 100644 index 0000000..2d4ff97 --- /dev/null +++ b/css/color.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "", +"sources": [], +"names": [], +"file": "color.css" +} \ No newline at end of file diff --git a/css/color.scss b/css/color.scss new file mode 100644 index 0000000..331b06c --- /dev/null +++ b/css/color.scss @@ -0,0 +1,2 @@ +$mainColor :#0061a9; +$mainColor2 : #707070; \ No newline at end of file diff --git a/css/company.css b/css/company.css new file mode 100644 index 0000000..fe2567b --- /dev/null +++ b/css/company.css @@ -0,0 +1,1040 @@ +@charset "UTF-8"; +em { + color: #0061a9; } + +b { + font-weight: 600; } + +.introduceContainer > p { + display: none; } +.introduceContainer > ul { + position: relative; + width: 1200px; + margin: 150px auto 50px; } + .introduceContainer > ul:after { + position: absolute; + top: -100px; + left: 100px; + font-size: 24px; + font-weight: 700; + content: '인사말'; } + .introduceContainer > ul > li { + text-align: center; } + .introduceContainer > ul > li:nth-child(1) { + width: 1000px; + margin: 0 auto; + letter-spacing: 0px; + font-weight: 600; + font-size: 18px; + line-height: 1.3em; + text-align: left; } + .introduceContainer > ul > li:nth-child(2) { + width: 1000px; + margin: 0 auto; + padding-top: 20px; + font-size: 15px; + line-height: 1.75em; + text-align: justify; } + .introduceContainer > ul > li:nth-child(2) > em { + margin-top: 20px; + display: block; + font-size: 23px; + font-weight: 900; + text-align: right; } +.introduceContainer > .normalInfo { + position: relative; + width: 100%; + height: 500px; + background-image: url(../images/one.jpg); + background-attachment: fixed; + background-position: 50% 10%; } + .introduceContainer > .normalInfo:after { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: transparent; + content: ''; } + .introduceContainer > .normalInfo > .normalInfoInner { + width: 1200px; + margin: 0 auto; + padding-left: 200px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul { + margin-top: 120px; + float: left; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > li { + float: left; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 { + position: relative; + width: 300px; + height: 300px; + background-color: #0061a9; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1:after { + position: absolute; + top: -50px; + left: 0; + font-size: 24px; + font-weight: 700; + color: #000; + content: '일반현황'; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl { + width: 250px; + margin: 0 auto; + text-align: center; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > dt { + margin-top: 100px; + width: 250px; + height: 60px; + text-indent: -999999px; + background: url(../images/logo_w.png); + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > dd { + color: #fff; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > dd > em { + font-weight: 600; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > dd:last-child { + margin-top: 60px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > .info_name { + font-size: 20px; + font-weight: 600; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > .info_shot { + font-size: 12px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child { + margin-left: 50px; + width: 670px; + background-color: rgba(255, 255, 255, 0.4); } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li { + float: left; + font-size: 16px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li > dl dd { + height: 42px; + line-height: 42px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:first-child > dl > dd { + padding: 0 20px; + text-align: justify; + text-align-last: justify; + color: #fff; + font-weight: 600; + background-color: #0061a9; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:last-child { + width: 82%; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:last-child > dl > dd { + width: 100%; + padding-left: 10px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:last-child > dl > dd:last-child { + border-bottom: none; } + +.organization { + width: 1200px; + height: 600px; + margin: 0 auto; + background-image: url(../images/organigation_2.jpg); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; } + .organization > p { + margin: 50px 0 0 100px; + font-size: 24px; + font-weight: 700; + color: #000; } + +.welfareContainer { + padding: 50px 0 100px; + width: 100%; } + .welfareContainer > .welfare_head { + width: 1200px; + margin: 80px auto; + text-align: center; } + .welfareContainer > .welfare_head > ul li:first-child { + margin-bottom: 30px; + font-size: 30px; + font-weight: 600; } + .welfareContainer > .welfare_head > ul li:last-child { + line-height: 1.6em; + font-size: 18px; } + .welfareContainer > .welfare_body { + width: 904px; + margin: 0 auto; + text-align: center; } + .welfareContainer > .welfare_body > ul > li { + width: 300px; + height: 300px; + float: left; + border: 1px solid #0061a9; + border-right: 0; } + .welfareContainer > .welfare_body > ul > li > dl > dt { + position: relative; + margin-top: 150px; + font-size: 30px; + font-weight: 600; } + .welfareContainer > .welfare_body > ul > li > dl > dt:after { + position: absolute; + top: -80px; + left: 50%; + width: 70px; + height: 70px; + transform: translateX(-50%); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + content: ''; } + .welfareContainer > .welfare_body > ul > li > dl > dd { + padding-top: 5px; + line-height: 1.4em; + color: #bbb; + font-weight: 600; } + .welfareContainer > .welfare_body > ul > li:nth-child(2) > dl > dt:after { + background-image: url(../images/company_work.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(3) > dl > dt:after { + background-image: url(../images/education.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(4) > dl > dt:after { + background-image: url(../images/help.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(5) > dl > dt:after { + background-image: url(../images/clock.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(6) > dl > dt:after { + background-image: url(../images/money.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(1), .welfareContainer > .welfare_body > ul > li:nth-child(2), .welfareContainer > .welfare_body > ul > li:nth-child(3) { + border-bottom: 0; } + .welfareContainer > .welfare_body > ul > li:nth-child(3), .welfareContainer > .welfare_body > ul > li:nth-child(6) { + border-right: 1px solid #0061a9; } + .welfareContainer > .welfare_body > ul > li:first-child { + background-color: #0061a9; + color: #fff; } + .welfareContainer > .welfare_body > ul > li:first-child > .wfS { + margin-top: 120px; } + .welfareContainer > .welfare_body > ul > li:first-child > .wfS > dt { + margin-top: 130px; + font-size: 22px; + padding-bottom: 3px; + font-weight: 500; } + .welfareContainer > .welfare_body > ul > li:first-child > .wfS dd { + padding-top: 0px; + font-size: 30px; + font-weight: 900; + color: #fff; } + +.certificationContainer { + width: 100%; + margin-bottom: 0 auto; + height: auto; + background-color: #fff; } + .certificationContainer > p { + display: none; } + .certificationContainer > .certificate { + position: relative; + width: 1000px; + margin: 0 auto; } + .certificationContainer > .certificate > ul { + margin-top: 80px; + width: 100%; } + .certificationContainer > .certificate > ul > li { + margin: 0 auto; + width: 200px; + margin-top: 20px; + text-align: center; + font-size: 40px; + font-weight: 600; + color: #333; } + .certificationContainer > .certificate > ul > li.status_info_main { + position: relative; + font-weight: 700; + color: #333; + font-size: 23px; + margin-bottom: 55px; + line-height: 1.3em; } + .certificationContainer > .certificate > ul > li > em { + color: #ddd; } + .certificationContainer > .certificate > ul > li > span { + font-size: 20px; } + .certificationContainer > .certificate > .certificate_info { + width: 100%; } + .certificationContainer > .certificate > .certificate_info > div { + width: 100%; } + .certificationContainer > .certificate > .certificate_info > div > ul > li { + float: left; + margin: 0 47px 50px 0; + width: 300px; + height: 400px; + border: 1px dotted #aaa; } + .certificationContainer > .certificate > .certificate_info > div > ul > li:last-child { + margin-right: 0; } + .certificationContainer > .certificate > .certificate_info > div > ul > li > dl > dt { + width: 300px; + height: 350px; + text-indent: -99999px; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + .certificationContainer > .certificate > .certificate_info > div > ul > li > dl > dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; } + .certificationContainer > .certificate > .certificate_info > .sect01 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_10.png); + background-size: contain; } + .certificationContainer > .certificate > .certificate_info > .sect01 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_12.png); + background-size: contain; } + .certificationContainer > .certificate > .certificate_info > .sect01 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_02.png); } + .certificationContainer > .certificate > .certificate_info > .sect02 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); } + .certificationContainer > .certificate > .certificate_info > .sect02 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); } + .certificationContainer > .certificate > .certificate_info > .sect02 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); } + .certificationContainer > .certificate > .certificate_info > .sect03 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); } + .certificationContainer > .certificate > .certificate_info > .sect03 > ul > li:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; } + .certificationContainer > .certificate > .certificate_info > .sect03 > ul > li:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_11.png); + background-position: 50% 50%; } + .certificationContainer > .certificate > .certificate_info > .sect04 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_13.png); + background-size: contain; } + .certificationContainer > .certificate > .certificate_info > .sect04 > ul > li:nth-child(2) > dl > dt { + background-size: contain; + background-position: 50% 50%; } + .certificationContainer > .certificate > .certificate_info > .sect04 > ul > li:nth-child(3) > dl > dt { + background-size: cover; + background-position: 50% 50%; } + +.careers { + width: 1200px; + height: 1600px; + margin: 0 auto; + background-image: url(../images/company_04_bg.png); + background-size: cover; + background-repeat: no-repeat; + border: 1px solid #eee; } + .careers .careersTitle { + padding: 10px 0; + width: 170px; + background-color: #0061a9; + text-align: center; + font-size: 23px; + color: #fff; } + .careers > .careersHeader { + position: relative; + width: 100%; + height: 370px; } + .careers > .careersHeader > ul > li { + position: absolute; } + .careers > .careersHeader > ul > li:first-child { + bottom: 10px; + right: 80px; + font-size: 100px; + font-weight: 600; } + .careers > .careersHeader > ul > li:last-child { + bottom: 10px; + left: 80px; + font-size: 30px; + line-height: 1.25em; } + .careers > .talent, .careers > .jobs, .careers > .other { + padding: 100px 80px 0; } + .careers > .talent > ul, .careers > .jobs > ul, .careers > .other > ul { + padding-top: 15px; } + .careers > .talent > ul > li, .careers > .jobs > ul > li, .careers > .other > ul > li { + position: relative; + padding-left: 25px; + font-size: 17px; + line-height: 2em; + color: #151515; } + .careers > .talent > ul > li:after, .careers > .jobs > ul > li:after, .careers > .other > ul > li:after { + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + color: #ccc; + content: '■'; } + .careers .jobs { + width: 100%; + height: 400px; } + .careers .jobs > .jobsContainer > ul { + position: relative; + cursor: pointer; + width: 1000px; + height: 150px; + margin-top: 20px; + border: 1px solid #ccc; + transition: all 0.3s ease-in-out; + box-sizing: border-box; } + .careers .jobs > .jobsContainer > ul:hover { + border-color: orange; + background-color: #f1f1f1; } + .careers .jobs > .jobsContainer > ul:nth-child(1):after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: 40px; + font-size: 70px; + font-weight: 600; + color: #0061a9; + content: "01"; } + .careers .jobs > .jobsContainer > ul:nth-child(2):after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: 40px; + font-size: 70px; + font-weight: 600; + color: #0061a9; + content: "02"; } + .careers .jobs > .jobsContainer > ul > li { + float: left; } + .careers .jobs > .jobsContainer > ul > li:first-child { + position: relative; + width: 70%; } + .careers .jobs > .jobsContainer > ul > li:first-child:after { + position: absolute; + bottom: 25px; + right: 0; + width: 95%; + height: 1px; + background-color: #ccc; + content: ''; } + .careers .jobs > .jobsContainer > ul > li:first-child > dl { + padding: 45px 0 0px 150px; } + .careers .jobs > .jobsContainer > ul > li:first-child > dl > dt { + font-size: 25px; + font-weight: 600; } + .careers .jobs > .jobsContainer > ul > li:first-child > dl > dd { + margin-top: 10px; + font-size: 17px; + color: #888; } + .careers .jobs > .jobsContainer > ul > li:first-child > dl .job_1 { + margin-bottom: 25px; } + .careers .jobs > .jobsContainer > ul > li:last-child { + width: 30%; + height: 100%; + text-indent: -99999px; + background-image: url(../images/company_02.jpg); + background-repeat: no-repeat; + background-size: cover; } + .careers .jobs > .jobsOverView { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999999; + background-color: rgba(0, 0, 0, 0.7); } + .careers .jobs > .jobsOverView > .close { + cursor: pointer; + margin: 30px; + padding: 10px; + text-align: right; + font-size: 50px; + color: #fff; } + .careers .jobs > .jobsOverView > ul { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 1000px; + height: 500px; + background-color: #fff; } + .careers .jobs > .jobsOverView > ul > li:first-child { + width: 100%; + height: 160px; + background-color: #bbb; + text-align: center; } + .careers .jobs > .jobsOverView > ul > li:first-child > dl { + width: 300px; + height: 100px; + margin: 0 auto; + padding-top: 30px; + color: #fff; } + .careers .jobs > .jobsOverView > ul > li:first-child > dl > dt { + padding: 5px 0; + width: 120px; + margin: 0 auto; + border: 2px solid #fff; + border-radius: 30px; + font-size: 16px; } + .careers .jobs > .jobsOverView > ul > li:first-child > dl > dd { + margin-top: 30px; + font-size: 26px; } + .careers .jobs > .jobsOverView > ul > li:last-child { + width: 100%; + height: 340px; + background-color: #f2f2f2; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li { + float: left; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:first-child { + width: 35%; + height: 340px; + font-size: 25px; + font-weight: 600; + text-align: center; + color: #0061a9; + line-height: 3em; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:last-child { + padding-top: 30px; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:last-child > dl > dt { + font-size: 20px; + padding-bottom: 15px; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:last-child > dl > dd { + font-size: 18px; + line-height: 2em; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:last-child > dl > dd > em { + font-weight: 600; } + +@media screen and (max-width: 768px) { + .introduceContainer { + position: relative; } + .introduceContainer > p { + display: block; + position: absolute; + top: 30px; + right: 30px; } + .introduceContainer > p > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .introduceContainer > ul { + width: 100%; + margin: 100px 0 30px; + text-align: center; } + .introduceContainer > ul:after { + display: none; + position: absolute; + top: -100px; + left: 100px; + font-size: 22px; + font-weight: 600; + content: '인사말'; } + .introduceContainer > ul > li { + text-align: center; + padding: 0 0px; } + .introduceContainer > ul > li:nth-child(1) { + width: 90%; + font-weight: 600; + font-size: 19px; + line-height: 1.3em; } + .introduceContainer > ul > li:nth-child(2) { + width: 90%; + padding-top: 20px; + font-size: 13px; + line-height: 2em; } + .introduceContainer > ul > li:nth-child(2) > br { + display: none; } + .introduceContainer > ul > li:nth-child(2) > em { + font-size: 16px; } + .introduceContainer > .normalInfo { + margin-bottom: 90px; + position: relative; + width: 100%; + height: auto; + background-image: none; + background-attachment: inherit; + background-color: #f1f1f1; + background-position: 50% 10%; } + .introduceContainer > .normalInfo:after { + display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: transparent; + content: ''; } + .introduceContainer > .normalInfo > .normalInfoInner { + width: 100%; + margin: 0 auto; + padding-left: 0px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul { + margin-top: 60px; + float: inherit; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > li { + float: left; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 { + position: relative; + margin-top: 70px; + width: 100%; + height: auto; + background-color: #666; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1:after { + position: absolute; + top: -50px; + left: 50%; + transform: translateX(-50%); + font-size: 20px; + font-weight: 700; + color: #000; + content: '일반현황'; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl { + width: 250px; + margin: 20px auto; + text-align: center; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > dt { + margin-top: 0px; + width: 250px; + height: 60px; + text-indent: -999999px; + background: url(../images/logo_w.png); + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > dd { + color: #fff; + line-height: 1.5em; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > dd > em { + font-weight: 600; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > dd:last-child { + margin-top: 0px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > .info_shot { + display: none; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:first-child > .info_1 > dl > .info_name { + font-size: 20px; + font-weight: 600; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child { + margin-top: -40px; + margin-left: 0px; + width: 100%; + background-color: rgba(255, 255, 255, 0.4); } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li { + float: left; + font-size: 16px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li > dl dd { + height: 30px; + line-height: 30px; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:first-child { + width: 100%; + background: #f1f1f1; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:first-child > dl > dd { + cursor: pointer; + width: 70px; + float: left; + padding: 0 7px; + border: 3px solid #0061a9; + margin: 3px 5px; + border-radius: 40px; + text-align: center; + text-align-last: center; + color: #fff; + font-weight: 600; + font-size: 13px; + background-color: #0061a9; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:first-child > dl > dd:hover { + background-color: #666; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:last-child { + position: relative; + width: 100%; + border-top: 1px solid #555; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:last-child > dl > dd { + position: absolute; + top: 0; + left: 0; + color: #fff; + background-color: #666; + font-size: 12px; + font-weight: 600; + width: calc(7/100%); + height: 100px; + line-height: 100px; + padding-left: 0px; + text-align: center; } + .introduceContainer > .normalInfo > .normalInfoInner > ul:last-child > li:last-child > dl > dd:last-child { + border-bottom: none; } + + .organization { + width: 100%; + height: 400px; + margin: 0 auto; + background-image: url(../images/organigation_2.jpg); + background-repeat: no-repeat; + background-position: 50% 70%; + background-size: 190%; } + .organization > p { + margin: 50px 0 0 50px; + font-size: 22px; + font-weight: 700; + color: #000; } + + .welfareContainer { + padding: 100px 0 0px; + width: 100%; } + .welfareContainer > .welfare_head { + width: 100%; + margin: 80px auto 20px; + text-align: center; } + .welfareContainer > .welfare_head > ul li { + padding: 0 20px; } + .welfareContainer > .welfare_head > ul li:first-child { + margin-bottom: 30px; + font-size: 25px; + font-weight: 600; } + .welfareContainer > .welfare_head > ul li:last-child { + line-height: 1.6em; + font-size: 14px; } + .welfareContainer > .welfare_head > ul li:last-child > br { + display: none; } + .welfareContainer > .welfare_body { + width: 100%; + margin: 0 auto; + text-align: center; } + .welfareContainer > .welfare_body > ul > li { + width: 100%; + height: 100%; + float: inherit; + border: 1px solid #0061a9; + border-right: 0; } + .welfareContainer > .welfare_body > ul > li > dl > dt { + position: relative; + margin-top: 100px; + font-size: 30px; + font-weight: 600; } + .welfareContainer > .welfare_body > ul > li > dl > dt:after { + position: absolute; + top: -80px; + left: 50%; + width: 70px; + height: 70px; + transform: translateX(-50%); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + content: ''; } + .welfareContainer > .welfare_body > ul > li > dl > dd { + margin-bottom: 20px; + padding-top: 5px; + line-height: 1.4em; + color: #bbb; + font-weight: 600; } + .welfareContainer > .welfare_body > ul > li:nth-child(2) > dl > dt:after { + background-image: url(../images/company_work.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(3) > dl > dt:after { + background-image: url(../images/education.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(4) > dl > dt:after { + background-image: url(../images/help.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(5) > dl > dt:after { + background-image: url(../images/clock.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(6) > dl > dt:after { + background-image: url(../images/money.png); + content: ''; } + .welfareContainer > .welfare_body > ul > li:nth-child(1), .welfareContainer > .welfare_body > ul > li:nth-child(2), .welfareContainer > .welfare_body > ul > li:nth-child(3) { + border-bottom: 1px solid #0061a9; } + .welfareContainer > .welfare_body > ul > li:nth-child(3), .welfareContainer > .welfare_body > ul > li:nth-child(6) { + border-right: 0px solid #0061a9; } + .welfareContainer > .welfare_body > ul > li:nth-child(6) { + border-bottom: 2px solid #0061a9; } + .welfareContainer > .welfare_body > ul > li:first-child { + background-color: #0061a9; + color: #fff; } + .welfareContainer > .welfare_body > ul > li:first-child > .wfS { + margin-top: 30px; } + .welfareContainer > .welfare_body > ul > li:first-child > .wfS > dt { + margin-top: 0px; + font-size: 22px; + padding-bottom: 3px; + font-weight: 500; } + .welfareContainer > .welfare_body > ul > li:first-child > .wfS dd { + padding-top: 0px; + font-size: 30px; + font-weight: 900; + color: #fff; } + + .certificationContainer { + position: relative; + width: 100%; + margin-bottom: 0 auto; + height: auto; + background-color: #fff; } + .certificationContainer > p { + display: block; + position: absolute; + top: 30px; + right: 30px; } + .certificationContainer > p > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .certificationContainer > .certificate { + position: relative; + width: 100%; + margin: 0 auto; } + .certificationContainer > .certificate > ul { + margin-top: 80px; + width: 100%; } + .certificationContainer > .certificate > ul > li { + margin: 0 auto; + width: 100%; + margin-top: 20px; + text-align: center; + font-size: 40px; + font-weight: 600; + color: #333; } + .certificationContainer > .certificate > ul > li.status_info_main { + position: relative; + font-weight: 700; + color: #333; + margin-bottom: 55px; + line-height: 1.3em; } + .certificationContainer > .certificate > ul > li > em { + color: #ddd; } + .certificationContainer > .certificate > ul > li > span { + font-size: 20px; } + .certificationContainer > .certificate > .certificate_info { + width: 100%; } + .certificationContainer > .certificate > .certificate_info > div { + width: 100%; } + .certificationContainer > .certificate > .certificate_info > div > ul > li { + float: inherit; + margin: 0 47px 50px 0; + width: 100%; + height: 400px; + border: 1px dotted #aaa; + border-right: none; + border-left: none; } + .certificationContainer > .certificate > .certificate_info > div > ul > li:last-child { + margin-right: 0; } + .certificationContainer > .certificate > .certificate_info > div > ul > li > dl > dt { + width: 100%; + height: 350px; + text-indent: -99999px; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; } + .certificationContainer > .certificate > .certificate_info > div > ul > li > dl > dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; } + .certificationContainer > .certificate > .certificate_info > .sect01 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_10.png); } + .certificationContainer > .certificate > .certificate_info > .sect01 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_12.png); } + .certificationContainer > .certificate > .certificate_info > .sect01 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_02.png); } + .certificationContainer > .certificate > .certificate_info > .sect02 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); } + .certificationContainer > .certificate > .certificate_info > .sect02 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); } + .certificationContainer > .certificate > .certificate_info > .sect02 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); } + .certificationContainer > .certificate > .certificate_info > .sect03 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); } + .certificationContainer > .certificate > .certificate_info > .sect03 > ul > li:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; } + .certificationContainer > .certificate > .certificate_info > .sect03 > ul > li:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_11.png); + background-position: 50% 50%; } + + .careers { + width: 100%; + height: auto; + margin: 0 auto; + background-image: url(../images/company_04_bg.png); + background-size: cover; + background-repeat: no-repeat; + border: 0px solid #eee; } + .careers .careersTitle { + padding: 10px 0; + width: 170px; + background-color: #0061a9; + text-align: center; + font-size: 30px; + color: #fff; } + .careers > .careersHeader { + position: relative; + width: 100%; + height: 370px; } + .careers > .careersHeader > ul > li { + width: 100%; + position: inherit; } + .careers > .careersHeader > ul > li:first-child { + padding-top: 100px; + padding-bottom: 30px; + text-align: center; + bottom: 0px; + right: 0px; + font-size: 100px; + font-weight: 600; } + .careers > .careersHeader > ul > li:last-child { + padding: 0px; + text-align: center; + bottom: 10px; + left: 80px; + font-size: 25px; + line-height: 1.25em; } + .careers > .careersHeader > ul > li:last-child > br { + display: none; } + .careers > .talent, .careers > .jobs, .careers > .other { + padding: 100px 0px 0; } + .careers > .talent > ul, .careers > .jobs > ul, .careers > .other > ul { + padding-top: 15px; } + .careers > .talent > ul > li, .careers > .jobs > ul > li, .careers > .other > ul > li { + position: relative; + padding: 0 20px; + font-size: 15px; + line-height: 2em; + color: #151515; } + .careers > .talent > ul > li:after, .careers > .jobs > ul > li:after, .careers > .other > ul > li:after { + display: none; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + color: #ccc; + content: '■'; } + .careers .jobs { + width: 100%; + height: 400px; + padding-left: 0; } + .careers .jobs > .jobsContainer > ul { + position: relative; + cursor: pointer; + width: 100%; + height: 150px; + margin-top: 30px; + border: 1px solid #ccc; + transition: border-color 0.3s; + box-sizing: border-box; } + .careers .jobs > .jobsContainer > ul:hover { + border-color: orange; } + .careers .jobs > .jobsContainer > ul:nth-child(1):after { + position: absolute; + top: 35%; + transform: translateY(-50%); + left: 20px; + font-size: 70px; + font-weight: 600; + color: #0061a9; + content: "01"; } + .careers .jobs > .jobsContainer > ul:nth-child(2):after { + position: absolute; + top: 35%; + transform: translateY(-50%); + left: 20px; + font-size: 70px; + font-weight: 600; + color: #0061a9; + content: "02"; } + .careers .jobs > .jobsContainer > ul > li { + float: inherit; } + .careers .jobs > .jobsContainer > ul > li:first-child { + position: relative; + width: 100%; } + .careers .jobs > .jobsContainer > ul > li:first-child:after { + position: absolute; + bottom: 30px; + right: 0; + width: 100%; + height: 1px; + background-color: #ccc; + content: ''; } + .careers .jobs > .jobsContainer > ul > li:first-child > dl { + padding: 30px 0 0px 120px; } + .careers .jobs > .jobsContainer > ul > li:first-child > dl > dt { + font-size: 20px; + font-weight: 600; } + .careers .jobs > .jobsContainer > ul > li:first-child > dl > dd { + margin-top: 10px; + font-size: 20px; + color: #ccc; } + .careers .jobs > .jobsContainer > ul > li:first-child > dl .job_1 { + margin-bottom: 40px; } + .careers .jobs > .jobsContainer > ul > li:last-child { + display: none; + width: 30%; + height: 100%; + text-indent: -99999px; + background-image: url(../images/company_02.jpg); + background-repeat: no-repeat; + background-size: cover; } + .careers .jobs > .jobsOverView { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999999; + background-color: rgba(0, 0, 0, 0.7); } + .careers .jobs > .jobsOverView > ul { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + height: 480px; + background-color: #fff; } + .careers .jobs > .jobsOverView > ul > li:first-child { + width: 100%; + height: 100px; + background-color: #bbb; + text-align: center; } + .careers .jobs > .jobsOverView > ul > li:first-child > dl { + width: 100%; + height: 50px; + margin: 0 auto; + padding-top: 15px; + color: #fff; } + .careers .jobs > .jobsOverView > ul > li:first-child > dl > dt { + padding: 5px 0; + width: 120px; + margin: 0 auto; + border: 2px solid #fff; + border-radius: 30px; + font-size: 16px; } + .careers .jobs > .jobsOverView > ul > li:first-child > dl > dd { + margin-top: 10px; + font-size: 26px; } + .careers .jobs > .jobsOverView > ul > li:last-child { + width: 100%; + height: auto; + background-color: #f2f2f2; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li { + float: inherit; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:first-child { + width: 100%; + height: auto; + font-size: 20px; + font-weight: 600; + text-align: center; + color: #0061a9; + line-height: 3em; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:last-child { + height: 320px; + padding-top: 0px; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:last-child > dl { + padding: 0 20px; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:last-child > dl > dt { + font-size: 15px; + padding-bottom: 15px; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:last-child > dl > dd { + font-size: 13px; + line-height: 2em; } + .careers .jobs > .jobsOverView > ul > li:last-child > ul > li:last-child > dl > dd > em { + font-weight: 600; } + .careers > .other { + margin-bottom: 80px; } } + +/*# sourceMappingURL=company.css.map */ diff --git a/css/company.css.map b/css/company.css.map new file mode 100644 index 0000000..ea8d882 --- /dev/null +++ b/css/company.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["company.scss"], +"names": [], +"file": "company.css" +} \ No newline at end of file diff --git a/css/company.scss b/css/company.scss new file mode 100644 index 0000000..11a1264 --- /dev/null +++ b/css/company.scss @@ -0,0 +1,1809 @@ +$mainColor :#0061a9; +//$mainColor2 : #707070; + + + +em { + color: #0061a9; +} + +b { + font-weight: 600; +} + +.introduceContainer { + + >p { + display: none; + } + + + >ul { + position: relative; + width: 1200px; + margin: 150px auto 50px; + + &:after { + position: absolute; + top: -100px; + left: 100px; + font-size: 24px; + font-weight: 700; + content: '인사말'; + } + + + + >li { + text-align: center; + + &:nth-child(1) { + width: 1000px; + margin: 0 auto; + letter-spacing: 0px; + font-weight: 600; + font-size: 18px; + line-height: 1.3em; + text-align: left; + + + } + + &:nth-child(2) { + width: 1000px; + margin: 0 auto; + padding-top: 20px; + font-size: 15px; + line-height: 1.75em; + text-align: justify; + //text-align-last: justify; + + >em { + margin-top: 20px; + display: block; + font-size: 23px; + font-weight: 900; + text-align: right; + } + } + + } + }//end of ul + + >.normalInfo { //맨처음 + position: relative; + width: 100%; + height: 500px; + background-image: url(../images/one.jpg); + background-attachment: fixed; + background-position: 50% 10%; + + &:after { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: transparent; + content: ''; + } + + + >.normalInfoInner { + width: 1200px; + margin: 0 auto; + padding-left: 200px; + + >ul { + margin-top: 120px; + float: left; + + &:first-child { + + >li { + float: left; + + } + + >.info_1 { + position: relative; + width: 300px; + height: 300px; + background-color: #0061a9; + + &:after { + position: absolute; + top: -50px; + left: 0; + font-size: 24px; + font-weight: 700; + color: #000; + content: '일반현황'; + + } + + >dl { + width: 250px; + margin: 0 auto; + text-align: center; + + >dt { + margin-top: 100px; + width: 250px; + height: 60px; + text-indent: -999999px; + background:url(../images/logo_w.png); + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + }//logo + + >dd { + color: #fff; + + >em { + font-weight: 600; + } + + &:last-child { + margin-top: 60px; + } + + } + + >.info_name { + font-size: 20px; + font-weight: 600; + } + >.info_shot { + font-size: 12px; + } + + } + }//end of info_1 + + }//end of 첫번째 ul + + &:last-child { + margin-left: 50px; + width: 670px; + background-color:rgba(255,255,255,0.4); + //background-color:rgba(000,000,000,0.1); + + >li { + float: left; + font-size: 16px; + + >dl { + dd { + height: 42px; + line-height: 42px; + //border-bottom: 1px solid #eee; + } + } + + + &:first-child { + >dl >dd { + padding: 0 20px; + text-align: justify; + text-align-last: justify; + color: #fff; + font-weight: 600; + background-color: #0061a9; + + } + } + + &:last-child { + width: 82%; + >dl >dd { + width: 100%; + padding-left: 10px; + //border-bottom: 1px solid #ccc; + + &:last-child { + border-bottom: none; + } + + } + } + } + + }//end of 두번째 ul + + + + }//end of ul + } + + + + + + + + + }//end of normalInfo + + +}//end of introduceContainer + +.organization { + width: 1200px; + height: 600px; + margin: 0 auto; + background-image: url(../images/organigation_2.jpg); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + + >p { + margin: 50px 0 0 100px; + font-size: 24px; + font-weight: 700; + color: #000; + } + +}//end of organization + +.welfareContainer { + padding: 50px 0 100px; + width: 100%; + + >.welfare_head { + width: 1200px; + margin: 80px auto; + text-align: center; + + >ul { + li { + + &:first-child { + margin-bottom: 30px; + font-size: 30px; + font-weight: 600; + } + + &:last-child { + line-height: 1.6em; + font-size: 18px; + } + } + } + }//end of welfare_head + + >.welfare_body { + width: 904px; + margin: 0 auto; + text-align: center; + + + >ul { + + >li { + width: 300px; + height: 300px; + float: left; + border: 1px solid #0061a9; + border-right: 0; + + >dl { + + >dt { + position: relative; + margin-top: 150px; + font-size: 30px; + font-weight: 600; + + &:after { + position: absolute; + top: -80px; + left: 50%; + width: 70px; + height: 70px; + transform: translateX(-50%); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + content: ''; + }//복리후생의 아이콘들 after 기본값 + } + + >dd { + padding-top: 5px; + line-height: 1.4em; + color: #bbb; + font-weight: 600; + + } + }// 모든 dl css + + &:nth-child(2) { + + >dl>dt { + + &:after { + background-image: url(../images/company_work.png); + content: ''; + } + } + }// 근무제도 아이콘 + + &:nth-child(3) { + + >dl>dt { + + &:after { + background-image: url(../images/education.png); + content: ''; + } + } + }// 교육비 아이콘 + + &:nth-child(4) { + + >dl>dt { + + &:after { + background-image: url(../images/help.png); + content: ''; + } + } + }// 법적 복리후생 아이콘 + + &:nth-child(5) { + + >dl>dt { + + &:after { + background-image: url(../images/clock.png); + content: ''; + } + } + }// 탄력근무제 아이콘 + + &:nth-child(6) { + + >dl>dt { + + &:after { + background-image: url(../images/money.png); + content: ''; + } + } + }// 경조사비 지원 아이콘 + + + &:nth-child(1),&:nth-child(2),&:nth-child(3) { + border-bottom: 0; + }//겹침 선 제거 + + &:nth-child(3),&:nth-child(6) { + border-right: 1px solid #0061a9; + }//빈 선 추가 + + &:first-child { + background-color: #0061a9; + color: #fff; + + >.wfS{ + margin-top: 120px; + + >dt { + margin-top: 130px; + font-size: 22px; + padding-bottom: 3px; + font-weight: 500; + } + + dd { + padding-top: 0px; + font-size: 30px; + font-weight: 900; + color: #fff; + } + }// 첫번째 dl css + }//end of first li + + + + }//end of li + + }//end of welfare_body + + }//end of welfare_body +}//end of welfareContainer + +.certificationContainer { + width: 100%; + margin-bottom: 0 auto; + //background-color: green; + height: auto; + background-color: #fff; + + >p { + display: none; + } + + + >.certificate { + position: relative; + width: 1000px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin: 0 auto; + width: 200px; + margin-top: 20px; + text-align: center; + font-size: 40px; + font-weight: 600; + color: #333; + + &.status_info_main { + position: relative; + font-weight: 700; + color: #333; + font-size: 23px; + margin-bottom: 55px; + line-height: 1.3em; + + + }//end of ceo_info_main + + >em { + color: #ddd; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >.certificate_info { + width: 100%; + //background-color: green; + + >div { + width: 100%; + + >ul { + + >li { + float: left; + margin: 0 47px 50px 0; + width: 300px; + height: 400px; + //background-color: pink; + border: 1px dotted #aaa; + + &:last-child { + margin-right: 0; + } + + >dl { + + >dt { + width: 300px; + height: 350px; + text-indent: -99999px; + //background-color: orange; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + } + >dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; + } + }//end of all dl + }//end of all li + }//end of all ul + }//end of all div + + + >.sect01 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_10.png); + background-size: contain; + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_12.png); + background-size: contain; + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_02.png); + + } + + }//end of sect01 img + + >.sect02 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); + } + + }//end of sect02 img + + + >.sect03 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); + } + &:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; + } + &:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_11.png); + background-position: 50% 50%; + } + + + }//end of sect03 img + + >.sect04 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_11.png); + background-size: contain; + } + &:nth-child(2) > dl > dt { + background-size: contain; + background-position: 50% 50%; + } + &:nth-child(3) > dl > dt { + background-size: cover; + background-position: 50% 50%; + } + + + }//end of sect04 img + + }//end of certificate_info--> + + }//end of ceo_info + +}//end of certificate + + +.careers { + width: 1200px; + height: 1600px; + margin: 0 auto; + background-image: url(../images/company_04_bg.png); + background-size: cover; + background-repeat: no-repeat; + border: 1px solid #eee; + + .careersTitle { + padding: 10px 0; + width: 170px; + background-color: $mainColor; + text-align: center; + font-size: 23px; + color: #fff; + }//end of talent + + >.careersHeader { + position: relative;//하위 li테그 relative + width: 100%; + height: 370px; + + >ul { + + >li { + position: absolute; + + &:first-child { + bottom: 10px; + right: 80px; + font-size: 100px; + font-weight: 600; + + } + + &:last-child { + bottom: 10px; + left: 80px; + font-size: 30px; + line-height: 1.25em; + } + } + }//end of ul + }//end of careersHeader + + >.talent { + padding : 100px 80px 0; + + >ul { + padding-top: 15px; + + >li { + position: relative; + padding-left: 25px; + font-size: 17px; + line-height: 2em; + color: #151515; + + &:after { + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + color: #ccc; + content: '■'; + } + + } + } + + }//end of talent + + .jobs { + width: 100%; + height: 400px; + @extend .talent; + + >.jobsContainer { + >ul { + position: relative;// + cursor: pointer; + width: 1000px; + height: 150px; + margin-top: 20px; + border: 1px solid #ccc; + transition: all 0.3s ease-in-out; + box-sizing: border-box; + //background-color: #f5f5f5; + + &:hover { + border-color: orange; + background-color: #f1f1f1; + } + + + &:nth-child(1):after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: 40px; + font-size: 70px; + font-weight: 600; + color: $mainColor; + content: "01"; + } + + &:nth-child(2):after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: 40px; + font-size: 70px; + font-weight: 600; + color: $mainColor; + content: "02"; + + } + + >li { + float: left; + + &:first-child { + position: relative; + width: 70%; + //background-color: lightcoral; + + &:after { + position: absolute; + bottom: 25px; + right: 0; + width: 95%; + height: 1px; + background-color: #ccc; + content: ''; + } + + >dl { + padding : 45px 0 0px 150px; + + >dt { + font-size: 25px; + font-weight: 600; + } + + >dd { + margin-top: 10px; + font-size: 17px; + color: #888; + } + .job_1 { + + margin-bottom : 25px; + + } + } + } + &:last-child { + width: 30%; + height: 100%; + text-indent: -99999px; + background-image: url(../images/company_02.jpg); + background-repeat: no-repeat; + background-size: cover; + } + } + } + }//end of jobsContainer + + >.jobsOverView { + display: none; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999999; + background-color: rgba(000,000,000,0.7); + + >.close { + cursor: pointer; + margin: 30px; + padding: 10px; + text-align: right; + font-size: 50px; + color: #fff; + } + + + + >ul { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 1000px; + height: 500px; + background-color: #fff; + + >li { + &:first-child { + width: 100%; + height: 160px; + background-color: #bbb; + text-align: center; + + >dl { + width: 300px; + height: 100px; + margin: 0 auto; + padding-top: 30px; + color: #fff; + + >dt { + + padding: 5px 0; + width: 120px; + margin: 0 auto; + border: 2px solid #fff; + border-radius: 30px; + font-size: 16px; + } + + >dd { + margin-top: 30px; + font-size: 26px; + } + } + }//first li + + &:last-child { + width: 100%; + height: 340px; + background-color: #f2f2f2; + + >ul { + >li { + float: left; + + &:first-child { + width: 35%; + height: 340px; + font-size: 25px; + font-weight: 600; + text-align: center; + color: $mainColor; + line-height: 3em; + } + + &:last-child { + padding-top: 30px; + + >dl { + >dt { + font-size: 20px; + padding-bottom : 15px; + + } + >dd { + font-size: 18px; + line-height: 2em; + + >em { + font-weight: 600; + } + } + } + } + } + } + }//last li + } + + } + }//end of jobsOverView + + + }//end of jobs + + >.other { + @extend .talent; + + } +}//end of careers + + + + + + + + +@media screen and (max-width:768px) { + + .introduceContainer { + position: relative; + >p { + display: block; + position: absolute; + top: 30px; + right: 30px; + + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + + } + + >ul { + width: 100%;//1200px + margin: 100px 0 30px;//100px auto + text-align: center; + + &:after { + display: none; + position: absolute; + top: -100px; + left: 100px; + font-size: 22px; + font-weight: 600; + content: '인사말'; + } + + >li { + text-align: center; + padding: 0 0px;//추가 0 0 + + &:nth-child(1) { + width: 90%;//추가 + font-weight: 600; + font-size: 19px;//35px + line-height: 1.3em; + + } + + &:nth-child(2) { + width: 90%;//추가 + padding-top: 20px; + font-size: 13px;//20px + line-height: 2em; + + >br { + display: none; + } + + >em { + font-size: 16px; + } + } + + } + }//end of ul + + >.normalInfo { //맨처음 + margin-bottom: 90px; + position: relative; + width: 100%; + height: auto;//500px + background-image: none;//변경 + background-attachment: inherit; + background-color: #f1f1f1; + background-position: 50% 10%; + + &:after { + display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: transparent; + content: ''; + } + + + >.normalInfoInner { + width: 100%; // 1200px + margin: 0 auto; + padding-left: 0px; //200px + + >ul { + margin-top: 60px;//120px + float: inherit;//left + + &:first-child {//디비엔텍 로고 + + >li { + float: left; + + } + + >.info_1 { + position: relative; + margin-top: 70px;//추가 + width: 100%;//300px + height: auto;//300px + background-color: #666; + + &:after { + position: absolute; + top: -50px; + left: 50%; + transform: translateX(-50%); + font-size: 20px; + font-weight: 700; + color: #000; + content: '일반현황'; + + } + + >dl { + width: 250px; + margin: 20px auto;//40px + text-align: center; + + >dt { + margin-top: 0px; + width: 250px; + height: 60px; + text-indent: -999999px; + background:url(../images/logo_w.png); + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + }//logo + + >dd { + color: #fff; + line-height: 1.5em; + + >em { + font-weight: 600; + } + + &:last-child { + margin-top: 0px;//60px + } + + } + + >.info_shot { + display: none; + } + + >.info_name { + font-size: 20px; + font-weight: 600; + } + + } + }//end of info_1 + + }//end of 첫번째 ul + + &:last-child { + margin-top: -40px; + //overflow: hidden; + margin-left: 0px;//50px + width: 100%;//660px + background-color:rgba(255,255,255,0.4); + //background-color:rgba(000,000,000,0.1); + + >li { + float: left; + font-size: 16px; + + >dl { + dd { + height: 30px; + line-height: 30px; + //border-bottom: 1px solid #eee; + } + } + + + &:first-child { + width: 100%; + background: #f1f1f1; + + + >dl{ + + >dd { + cursor: pointer; + width: 70px; + float: left; + padding: 0 7px; + border: 3px solid #0061a9; + //margin-right: 10px; + margin: 3px 5px; + border-radius: 40px; + //box-sizing: border-box; + text-align: center;//justify + text-align-last: center;//justify + color: #fff; + font-weight: 600; + font-size: 13px; + background-color: #0061a9; + + &:hover { + background-color: #666; + } + + } + + }//end of dl + } + + &:last-child { + position: relative; + width: 100%; + border-top: 1px solid #555; + //background-color: green; + >dl >dd { + position: absolute;//추가 + top: 0;//추가 + left: 0;//추가 + color: #fff; + background-color: #666; + font-size: 12px; + font-weight: 600; + width: calc(7/100%);//추가 + height: 100px;//변경 + line-height: 100px;//추가 float: left; + padding-left: 0px;//20px + text-align: center;//추가 + //border-bottom: 1px solid #ccc; + + &:last-child { + border-bottom: none; + } + + } + } + } + + }//end of 두번째 ul + + }//end of ul + }//end of normalInfoInner + + + }//end of normalInfo + + }//end of introduceContainer + + + .organization { + width: 100%; + height: 400px; + margin: 0 auto; + background-image: url(../images/organigation_2.jpg); + background-repeat: no-repeat; + background-position: 50% 70%; + background-size: 190%; + + >p { + margin: 50px 0 0 50px; + font-size: 22px; + font-weight: 700; + color: #000; + } + + }//end of organization + + + + + .welfareContainer { + padding: 100px 0 0px;//50px 0 100px + width: 100%; + + >.welfare_head { + width: 100%;//1200px + margin: 80px auto 20px;// 하단 20px 추가 + text-align: center; + + >ul { + li { + padding: 0 20px; + + &:first-child { + margin-bottom: 30px; + font-size: 25px; + font-weight: 600; + } + + &:last-child { + line-height: 1.6em; + font-size: 14px; + + >br { + display: none; + } + } + } + } + }//end of welfare_head + + >.welfare_body { + width: 100%;//904px + margin: 0 auto; + text-align: center; + + + >ul { + + >li { + width: 100%;//300px + height: 100%;//300px + float: inherit;//left + border: 1px solid #0061a9; + border-right: 0; + + >dl { + + >dt { + position: relative; + margin-top: 100px; + font-size: 30px; + font-weight: 600; + + &:after { + position: absolute; + top: -80px; + left: 50%; + width: 70px; + height: 70px; + transform: translateX(-50%); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + content: ''; + }//복리후생의 아이콘들 after 기본값 + } + + >dd { + margin-bottom: 20px; + padding-top: 5px; + line-height: 1.4em; + color: #bbb; + font-weight: 600; + + } + }// 모든 dl css + + &:nth-child(2) { + + >dl>dt { + + &:after { + background-image: url(../images/company_work.png); + content: ''; + } + } + }// 근무제도 아이콘 + + &:nth-child(3) { + + >dl>dt { + + &:after { + background-image: url(../images/education.png); + content: ''; + } + } + }// 교육비 아이콘 + + &:nth-child(4) { + + >dl>dt { + + &:after { + background-image: url(../images/help.png); + content: ''; + } + } + }// 법적 복리후생 아이콘 + + &:nth-child(5) { + + >dl>dt { + + &:after { + background-image: url(../images/clock.png); + content: ''; + } + } + }// 탄력근무제 아이콘 + + &:nth-child(6) { + + >dl>dt { + + &:after { + background-image: url(../images/money.png); + content: ''; + } + } + }// 경조사비 지원 아이콘 + + + &:nth-child(1),&:nth-child(2),&:nth-child(3) { + border-bottom: 1px solid #0061a9; + }//겹침 선 제거 + + &:nth-child(3),&:nth-child(6) { + border-right: 0px solid #0061a9;//border-right: 1px solid #0061a9; + }//빈 선 추가 + + &:nth-child(6) { + border-bottom: 2px solid #0061a9; + } + + &:first-child { + background-color: #0061a9; + color: #fff; + + >.wfS{ + margin-top: 30px;////end of 120px + + >dt { + margin-top: 0px;//end of 130px + font-size: 22px; + padding-bottom: 3px; + font-weight: 500; + } + + dd { + padding-top: 0px; + font-size: 30px; + font-weight: 900; + color: #fff; + } + }// 첫번째 dl css + }//end of first li + + + + }//end of li + + }//end of welfare_body + + }//end of welfare_body + }//end of welfareContainer + + + + + .certificationContainer { + position: relative; + width: 100%; + margin-bottom: 0 auto; + //background-color: green; + height: auto;//1600px + background-color: #fff; + >p { + display: block; + position: absolute; + top: 30px; + right: 30px; + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + + } + + + >.certificate { + position: relative; + width: 100%;//1000px + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin: 0 auto; + width: 100%;//200px + margin-top: 20px; + text-align: center; + font-size: 40px; + font-weight: 600; + color: #333; + + &.status_info_main { + position: relative; + font-weight: 700; + color: #333; + margin-bottom: 55px; + line-height: 1.3em; + + + }//end of ceo_info_main + + >em { + color: #ddd; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >.certificate_info { + width: 100%; + //background-color: green; + + >div { + width: 100%; + + >ul { + + >li { + float: inherit;//left + margin: 0 47px 50px 0; + width: 100%;//300px + height: 400px; + //background-color: pink; + border: 1px dotted #aaa; + border-right: none; + border-left: none; + + &:last-child { + margin-right: 0; + } + + >dl { + + >dt { + width: 100%;//300px + height: 350px; + text-indent: -99999px; + //background-color: orange; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain;//cover + } + >dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; + } + }//end of all dl + }//end of all li + }//end of all ul + }//end of all div + + + >.sect01 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_10.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_12.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_02.png); + } + + }//end of sect01 img + + >.sect02 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); + } + + }//end of sect02 img + + + >.sect03 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); + } + &:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; + } + &:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_11.png); + background-position: 50% 50%; + } + + + + }//end of sect03 img + + }//end of certificate_info--> + + }//end of ceo_info + + }//end of certificate + + .careers { + width: 100%;//1200px + height: auto; + margin: 0 auto; + background-image: url(../images/company_04_bg.png); + background-size: cover; + background-repeat: no-repeat; + border: 0px solid #eee; + + .careersTitle { + padding: 10px 0; + width: 170px; + background-color: $mainColor; + text-align: center; + font-size: 30px; + color: #fff; + }//end of talent + + >.careersHeader { + position: relative;//하위 li테그 relative + width: 100%; + height: 370px; + + >ul { + + >li { + width: 100%; + position: inherit; + + &:first-child { + padding-top : 100px; + padding-bottom: 30px; + text-align: center; + bottom: 0px;//bottom: 80px; + right: 0px;//right: 80px; + font-size: 100px; + font-weight: 600; + + + + } + + &:last-child { + padding: 0px; + text-align: center; + bottom: 10px; + left: 80px; + font-size: 25px; + line-height: 1.25em; + + >br { + display: none; + } + } + } + }//end of ul + }//end of careersHeader + + >.talent { + padding : 100px 0px 0; + + >ul { + padding-top: 15px; + + >li { + position: relative; + padding: 0 20px ; + font-size: 15px; + line-height: 2em; + color: #151515; + + &:after { + display: none; + position: absolute; + top: 50%; + left: 0; + transform: translateY(-50%); + color: #ccc; + content: '■'; + } + + } + } + + }//end of talent + + .jobs { + width: 100%; + height: 400px; + padding-left : 0; + + >.jobsContainer { + >ul { + position: relative;// + cursor: pointer; + width: 100%; + height: 150px; + margin-top: 30px; + border: 1px solid #ccc; + transition: border-color 0.3s; + box-sizing: border-box; + //background-color: #f5f5f5; + + &:hover { + border-color: orange; + } + + + &:nth-child(1):after { + position: absolute; + top: 35%; + transform: translateY(-50%); + left: 20px; + font-size: 70px; + font-weight: 600; + color: $mainColor; + content: "01"; + } + + &:nth-child(2):after { + position: absolute; + top: 35%; + transform: translateY(-50%); + left: 20px; + font-size: 70px; + font-weight: 600; + color: $mainColor; + content: "02"; + + } + + >li { + float: inherit; + + &:first-child { + position: relative; + width: 100%; + //background-color: lightcoral; + + &:after { + position: absolute; + bottom: 30px; + right: 0; + width: 100%; + height: 1px; + background-color: #ccc; + content: ''; + } + + >dl { + padding : 30px 0 0px 120px; + + + + >dt { + + font-size: 20px; + font-weight: 600; + } + + >dd { + margin-top: 10px; + font-size: 20px; + color: #ccc; + } + .job_1 { + + margin-bottom : 40px; + + } + } + } + &:last-child { + display: none; + width: 30%; + height: 100%; + text-indent: -99999px; + background-image: url(../images/company_02.jpg); + background-repeat: no-repeat; + background-size: cover; + } + } + } + }//end of jobsContainer + + >.jobsOverView { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 999999; + background-color: rgba(000,000,000,0.7); + + + + >ul { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + height: 480px; + background-color: #fff; + + >li { + &:first-child { + width: 100%; + height: 100px; + background-color: #bbb; + text-align: center; + + >dl { + width: 100%; + height: 50px; + margin: 0 auto; + padding-top: 15px; + color: #fff; + + >dt { + + padding: 5px 0; + width: 120px; + margin: 0 auto; + border: 2px solid #fff; + border-radius: 30px; + font-size: 16px; + } + + >dd { + margin-top: 10px; + font-size: 26px; + } + } + }//first li + + &:last-child { + width: 100%; + height: auto; + background-color: #f2f2f2; + + >ul { + >li { + float: inherit; + + &:first-child { + width: 100%; + height: auto; + font-size: 20px; + font-weight: 600; + text-align: center; + color: $mainColor; + line-height: 3em; + } + + &:last-child { + height: 320px; + padding-top: 0px; + + + >dl { + padding: 0 20px; + >dt { + font-size: 15px; + padding-bottom : 15px; + + } + >dd { + font-size: 13px; + line-height: 2em; + + >em { + font-weight: 600; + } + } + } + } + } + } + }//last li + } + + } + }//end of jobsOverView + + + }//end of jobs + + >.other { + margin-bottom: 80px; + } + }//end of careers + + + + + + + +}//end of mediaQuery \ No newline at end of file diff --git a/css/contact.css b/css/contact.css new file mode 100644 index 0000000..53b0ffb --- /dev/null +++ b/css/contact.css @@ -0,0 +1,167 @@ +.subBanner { + width: 100%; + height: 200px; + background: url(../images/contact_b.jpg); + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; } + +.contactContainer { + position: relative; + width: 100%; } + .contactContainer > .contactInfo { + position: absolute; + top: 250px; + right: 20px; + width: 350px; + height: 330px; + background-color: #595959; + z-index: 5000; } + .contactContainer > .contactInfo > ul { + padding: 20px; } + .contactContainer > .contactInfo > ul > li { + width: 100%; + margin: 20px 0; + color: #fff; + font-size: 13px; } + .contactContainer > .contactInfo > ul > li > a { + color: #fff; } + .contactContainer > .contactInfo > ul > li:nth-child(1) { + font-size: 20px; + font-weight: 600; } + .contactContainer > .contactInfo > ul > li:nth-child(2) { + line-height: 1.5em; + font-size: 14px; } + .contactContainer > .contactInfo > ul > li:nth-child(3) { + width: 80%; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/email_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; } + .contactContainer > .contactInfo > ul > li:nth-child(4) { + width: 80%; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/tel_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; } + .contactContainer > .contactInfo > ul > li:nth-child(5) { + width: 80%; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/print_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; } + .contactContainer > p { + position: relative; + width: 1200px; + margin: 80px auto 0; + text-align: center; + font-size: 23px; + font-weight: 600; + color: #000; + text-transform: uppercase; } + .contactContainer > p:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left: -50px; + height: 5px; + background-color: #000; + content: ""; } + .contactContainer > .mapContainer { + margin-top: 100px; } + +@media screen and (max-width: 768px) { + .subBanner { + width: 100%; + height: 250px; + background: url(../images/contact_1.jpg); + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; } + + .contactContainer { + position: relative; + width: 100%; } + .contactContainer > .contactInfo { + position: inherit; + top: 100px; + right: 0px; + width: 100%; + height: 330px; + background-color: #595959; + z-index: 5000; } + .contactContainer > .contactInfo > ul { + padding: 20px; } + .contactContainer > .contactInfo > ul > li { + margin: 20px 0; + color: #fff; } + .contactContainer > .contactInfo > ul > li > a { + color: #fff; } + .contactContainer > .contactInfo > ul > li:nth-child(1) { + font-size: 25px; + font-weight: 600; } + .contactContainer > .contactInfo > ul > li:nth-child(2) { + line-height: 1.5em; } + .contactContainer > .contactInfo > ul > li:nth-child(3) { + width: 35px; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/email_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; } + .contactContainer > .contactInfo > ul > li:nth-child(4) { + width: 35px; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/tel_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; } + .contactContainer > .contactInfo > ul > li:nth-child(5) { + width: 35px; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/print_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; } + .contactContainer > p { + position: relative; + width: 100%; + margin: 80px auto 0; + text-align: center; + font-size: 23px; + font-weight: 600; + color: #000; + text-transform: uppercase; } + .contactContainer > p:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left: -50px; + height: 3px; + background-color: #000; + content: ""; } + .contactContainer > .mapContainer { + margin-top: 100px; } + + .mapContainer { + height: 400px; + overflow: hidden; } } + +/*# sourceMappingURL=contact.css.map */ diff --git a/css/contact.css.map b/css/contact.css.map new file mode 100644 index 0000000..1f86936 --- /dev/null +++ b/css/contact.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["contact.scss"], +"names": [], +"file": "contact.css" +} \ No newline at end of file diff --git a/css/contact.scss b/css/contact.scss new file mode 100644 index 0000000..6e837ad --- /dev/null +++ b/css/contact.scss @@ -0,0 +1,246 @@ +.subBanner { + width: 100%; + height: 200px; + background: url(../images/contact_b.jpg) ; + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; + +}//end of subBanner + + +.contactContainer { + position: relative; + width: 100%; + + + >.contactInfo { + position: absolute; + top: 250px; + right: 20px; + width: 350px; + height: 330px; + background-color: #595959; + z-index: 5000; + + >ul { + padding: 20px; + + >li { + width: 100%; + margin: 20px 0; + color: #fff; + font-size: 13px; + + >a { + color: #fff; + } + + + &:nth-child(1) { + font-size: 20px; + font-weight: 600; + + } + + &:nth-child(2) { + line-height: 1.5em; + font-size: 14px; + + } + + &:nth-child(3) { + width: 80%; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/email_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; + } + + &:nth-child(4) { + width: 80%; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/tel_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; + } + + &:nth-child(5) { + width: 80%; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/print_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; + } + + } + + + } + }//end of contactInfo + + >p { + position: relative; + width: 1200px; + margin: 80px auto 0; + text-align: center; + font-size: 23px; + font-weight: 600; + color: #000; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left : -50px; + height: 5px; + background-color: #000; + content: ""; + } + + } + + >.mapContainer { + margin-top: 100px; + } +}//end of contactContainer + + +@media screen and (max-width:768px) { + + .subBanner { + width: 100%; + height: 250px;// 350 + background: url(../images/contact_1.jpg) ; + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; + + }//end of subBanner + + + .contactContainer { + position: relative; + width: 100%; + + >.contactInfo { + position: inherit; + top: 100px;// 250px + right: 0px;//20px + width: 100%;//350px + height: 330px;//450px + background-color: #595959; + z-index: 5000; + + >ul { + padding: 20px; + + >li { + margin: 20px 0; + color: #fff; + + >a { + color: #fff; + } + + + &:nth-child(1) { + font-size: 25px; + font-weight: 600; + + } + + &:nth-child(2) { + line-height: 1.5em; + + } + + &:nth-child(3) { + width: 35px; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/email_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; + } + + &:nth-child(4) { + width: 35px; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/tel_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; + } + + &:nth-child(5) { + width: 35px; + height: 35px; + padding-left: 45px; + line-height: 35px; + background: url(../images/print_ico.png); + border-spacing: 0 0; + background-size: contain; + background-repeat: no-repeat; + } + + } + + + } + }//end of contactInfo + + + + >p { + position: relative; + width: 100%;//1200px + margin: 80px auto 0; + text-align: center; + font-size: 23px; + font-weight: 600; + color: #000; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left : -50px; + height: 3px; + background-color: #000; + content: ""; + } + + } + + >.mapContainer { + margin-top: 100px; + } + }//end of contactContainer + + + + .mapContainer { + height: 400px; + overflow: hidden; + } + + +}//media Query \ No newline at end of file diff --git a/css/layout.css b/css/layout.css new file mode 100644 index 0000000..aff3a2f --- /dev/null +++ b/css/layout.css @@ -0,0 +1,770 @@ +@charset "UTF-8"; +.popup { + position: fixed; + top: 200px; + left: 200px; + width: 400px; + height: 300px; + background: url(../images/pop.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + z-index: 999999999999; } + .popup p { + cursor: pointer; + position: absolute; + text-align: right; + bottom: 0px; + width: 100%; + color: #fff; + font-size: 20px; + font-weight: 600; + background: #0061a9; } + +.wrap { + width: 100%; } + +section { + padding-top: 61px; } + +.fxContainer { + position: fixed; + width: 100%; + z-index: 999999; + /*header 끝*/ } + .fxContainer header { + display: none; + width: 100%; + padding-left: 390px; + background-color: #fff; + border-bottom: 1px solid #dddddd; } + .fxContainer header > .inner > ul { + width: 200px; + margin-left: 25px; + border: 1px solid #dddddd; + border-top: none; + border-bottom: none; } + .fxContainer header > .inner > ul > li { + float: left; + width: 50%; + height: 35px; + line-height: 35px; + text-align: center; } + .fxContainer header > .inner > ul > li > a { + font-size: 12px; + color: #999999; } + .fxContainer header > .inner > ul > li > a:hover { + color: #333333; } + .fxContainer nav { + background-color: #fff; + width: 100%; + height: 60px; + border-bottom: 1px solid #dddddd; } + .fxContainer nav > .inner { + position: relative; + width: 1200px; + margin: 0 auto; } + .fxContainer nav > .inner > .logo { + float: left; + width: 130px; + margin-left: 40px; + text-indent: -99999px; } + .fxContainer nav > .inner > .logo > a { + display: block; + height: 50px; + background: url(../images/BULE.png); + background-repeat: no-repeat; + background-position: 50% 100%; + background-size: contain; } + .fxContainer nav > .inner > ul { + float: right; + width: 810px; } + .fxContainer nav > .inner > ul > li { + position: relative; + float: left; + width: 20%; + line-height: 60px; + text-align: left; } + .fxContainer nav > .inner > ul > li:nth-child(1) ul { + height: 145px; } + .fxContainer nav > .inner > ul > li:nth-child(2) ul { + height: 145px; } + .fxContainer nav > .inner > ul > li:nth-child(3) { + width: 25%; } + .fxContainer nav > .inner > ul > li:nth-child(3) ul { + margin: 0 auto; + width: 100%; + height: 145px; + letter-spacing: -1px; + text-align: left; } + .fxContainer nav > .inner > ul > li:nth-child(4) { + width: 25%; } + .fxContainer nav > .inner > ul > li:nth-child(5) { + width: 5%; + font-weight: 900; } + .fxContainer nav > .inner > ul > li:nth-child(5) > a { + color: #ddd; + transition: color 0.3s; } + .fxContainer nav > .inner > ul > li:nth-child(5) > a:hover { + color: #0061a9; } + .fxContainer nav > .inner > ul > li > .point { + position: absolute; + top: 56px; + left: 0%; + width: 2%; + height: 5px; + background-color: #0061a9; + content: ''; } + .fxContainer nav > .inner > ul > li > a { + display: block; + height: 60px; + font-size: 14px; + color: #333333; } + .fxContainer nav > .inner > ul > li > ul { + display: none; + width: 100%; + transition: 0.8s; } + .fxContainer nav > .inner > ul > li > ul > li { + line-height: 35px; + text-align: left; + padding-left: 0px; } + .fxContainer nav > .inner > ul > li > ul > li > a { + display: block; + color: #666; + width: 100%; + font-size: 13px; + font-weight: 500; } + .fxContainer nav > .inner > ul > li > ul > li > a:hover { + color: #0061a9; + font-weight: 700; + text-decoration: underline; } + .fxContainer nav > .language { + float: right; + width: 50px; + background-color: red; } + .fxContainer nav > .subMenuBg { + display: none; + position: absolute; + top: 60px; + left: 0; + width: 100%; + height: 145px; + border-bottom: 1px solid #d7d7d7; + background-color: #fff; + opacity: 0.95; + z-index: -1; } + +/*nav 끝*/ +/* +footer { + width: 100%; + //height: 170px; + background-color: #f1f1f1; + + >.inner { + width: 1200px; + position: relative; + padding-top: 20px; + //margin: 0 auto; + + >ul { + padding-top: 20px; + + >li { + float: left; + margin-right: 30px; + text-align: center; + font-size: 16px; + + >ul { + padding: 10px 0 20px; + + >li { + text-align: center; + font-size: 14px; + line-height: 40px; + + >a { + color: #999; + } + } + } + + &:last-child { + margin-right: 0; + } + } + }//end of ul + }//end of inner + + >.f_section { + width: 100%; + border-top: 1px solid #ddd; + padding: 20px 0; + + >ul { + width: 1200px; + margin: 0 auto; + + li { + float: left; + >img { + width: 160px; + } + + >dl { + color: #000; + dt { + line-height: 1.7em; + + >em { + color: #0061a9; + font-weight: 600; + } + + } + + dd { + line-height: 1.7em; + >span { + >em { + color: #0061a9; + font-weight: 600; + } + >a { + color: #000; + } + } + + } + } + } + }//end of ul + }//end of f_section +}//end of footer +*/ +footer { + width: 100%; + height: 170px; + background-color: #444; } + footer > .inner { + position: relative; + width: 1200px; + margin: 0 auto; + padding-top: 20px; } + footer > .inner > h1 { + float: left; + margin-left: 40px; + width: 130px; + height: 50px; + text-indent: -99999px; + background-image: url(../images/logo_w.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; } + footer > .inner > .f_left { + float: left; + margin-left: 50px; } + footer > .inner > .f_left > ul { + width: 280px; } + footer > .inner > .f_left > ul > li { + width: 400px; + text-align: center; } + footer > .inner > .f_left > ul > li > dl > dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + footer > .inner > .f_left > ul > li > dl > dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + line-height: 1.2em; + color: #fff; } + footer > .inner > .f_left > ul > li > dl > dd > em { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a:hover { + text-decoration: underline; } + footer > .inner > address { + float: left; + margin-top: 0px; + margin-left: 30px; + width: 340px; } + footer > .inner > address > ul { + width: 350px; } + footer > .inner > address > ul > li { + width: 320px; + text-align: center; } + footer > .inner > address > ul > li:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); } + footer > .inner > address > ul > li:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); } + footer > .inner > address > ul > li:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); } + footer > .inner > address > ul > li > dl > dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + footer > .inner > address > ul > li > dl > dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > address > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a:hover { + text-decoration: underline; } + footer > .inner > .f_nav { + float: right; + margin-top: 0px; + width: 270px; } + footer > .inner > .f_nav > ul > li { + width: calc(270px/5+ (9*5)); + float: left; + text-align: right; + margin-right: 9px; + background-image: url(../images/f_right.png); + background-repeat: no-repeat; + background-position: 100% 73%; } + footer > .inner > .f_nav > ul > li:last-child { + margin-right: none; + background-image: none; } + footer > .inner > .f_nav > ul > li > a { + font-size: 13px; + color: #fff; } + footer > .inner > .copyright { + position: absolute; + top: 120px; + right: -141px; + transform: translateX(-50%); + width: 315px; + font-size: 13px; + letter-spacing: 1px; + color: #fff; } + footer > .inner:after { + position: absolute; + top: 30px; + left: 200px; + transform: translateX(-50%); + width: 1px; + height: 120px; + background-color: #808080; + content: ''; } + footer > .inner > .snsBox{ + position: absolute; + right: 11px; + top: 85px; } + footer > .inner > .snsBox > ul > li:nth-child(1) a { + width: 45px; + height: 30px; + font-size: 13px; + color: #fff; + background: url('../images/footer_ico/youtube.png') no-repeat; + background-size: 30px; + display: block; } +/*footer 끝*/ +/* +*************************************************************************** +RW 적용 CSS**************************************************************** +*************************************************************************** +*/ +@media screen and (max-width: 768px) { + .toggleActive { + background-image: url(../images/toggle_cls.png) !important; } + + .toggleActiveSub { + display: block !important; } + + .fxContainer { + position: fixed; + width: 100%; + z-index: 999999; + /*header 끝*/ } + .fxContainer > .mobileToggle { + cursor: pointer; + position: absolute; + top: 0; + right: 0; + width: 100px; + height: 60px; + background-image: url(../images/toggle.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 70%; + z-index: 9999999; } + .fxContainer header { + display: none; + width: 100%; + padding-left: 390px; + background-color: #fff; + border-bottom: 1px solid #dddddd; } + .fxContainer header > .inner > ul { + width: 200px; + margin-left: 25px; + border: 1px solid #dddddd; + border-top: none; + border-bottom: none; } + .fxContainer header > .inner > ul > li { + float: left; + width: 50%; + height: 35px; + line-height: 35px; + text-align: center; } + .fxContainer header > .inner > ul > li > a { + font-size: 12px; + color: #999999; } + .fxContainer header > .inner > ul > li > a:hover { + color: #333333; } + .fxContainer nav { + width: 100%; + height: 60px; + border-bottom: 1px solid #dddddd; } + .fxContainer nav > .inner { + position: relative; + width: 100%; + height: 100%; + margin: 0 auto; } + .fxContainer nav > .inner > .logo { + float: left; + width: 130px; + margin-left: 0px; + text-indent: -99999px; } + .fxContainer nav > .inner > .logo > a { + display: block; + margin-top: 10px; + height: 40px; + background: url(../images/BULE.png); + background-repeat: no-repeat; + background-position: 80% -50%; + background-size: cover; } + .fxContainer nav > .inner > ul { + display: none; + float: right; + margin-top: 11px; + width: 100%; } + .fxContainer nav > .inner > ul > li { + position: relative; + float: inherit; + width: 100%; + line-height: 60px; + text-align: center; + background-color: #666; + border-bottom: 1px solid #444; } + .fxContainer nav > .inner > ul > li:nth-child(1) ul { + height: auto; } + .fxContainer nav > .inner > ul > li:nth-child(2) ul { + height: auto; } + .fxContainer nav > .inner > ul > li:nth-child(3) { + width: 100%; } + .fxContainer nav > .inner > ul > li:nth-child(3) > ul { + width: 100%; + height: auto; + text-align: center; + text-align-last: inherit; + letter-spacing: 0px; } + .fxContainer nav > .inner > ul > li:nth-child(4) { + width: 100%; } + .fxContainer nav > .inner > ul > li:last-child { + width: 100%; } + .fxContainer nav > .inner > ul > li > .point { + position: absolute; + top: 56px; + left: 50%; + transform: translateX(-50%); + width: 0%; + height: 5px; + background-color: #0061a9; + content: ''; } + .fxContainer nav > .inner > ul > li > a { + display: block; + height: 60px; + color: #fff; } + .fxContainer nav > .inner > ul > li > ul { + display: none; + width: 100%; + transition: 0.8s; } + .fxContainer nav > .inner > ul > li > ul > li { + display: none; + text-align: center; + line-height: 45px; + background-color: #ddd; + border-bottom: 1px solid #bbb; } + .fxContainer nav > .inner > ul > li > ul > li > a { + display: block; + color: #666; + font-size: 14px; + font-weight: 00; } + .fxContainer nav > .inner > ul > li > ul > li > a:hover { + color: #0061a9; + font-weight: 500; } + .fxContainer nav > .subMenuBg { + display: none; + position: absolute; + top: 60px; + left: 0; + width: 100%; + height: 190px; + border-bottom: 1px solid #d7d7d7; + background-color: #fff; + opacity: 0.95; + z-index: -1; } + + /* + footer {// end of footer 768px + width: 100%; + background-color: #f1f1f1; + + >.inner { + width: 100%; // 1200px + margin: 0 auto; + + >ul { + padding-top: 20px; + + >li { + float: inherit; //left + margin-right: 0px;//30px + text-align: center; + font-size: 16px; + + >ul { + padding: 10px 0 20px; + + >li { + text-align: center; + font-size: 14px; + line-height: 40px; + + >a { + color: #999; + } + } + } + + &:last-child { + margin-right: 0; + } + } + }//end of ul + }//end of inner + + >.f_section { + width: 100%; + border-top: 1px solid #ddd; + padding: 20px 0; + + >ul { + width: 100%;//1200px + margin: 0 auto; + + li { + float: inherit; + + >img { + display: block; + width: 160px; + margin: 0 auto; + } + + >dl { + padding: 0 0px;// 0 25px + dt { + line-height: 1.7em; + border-bottom: 1px solid #888;//추가 + padding: 0px 25px 10px;//추가 + + } + + dd { + line-height: 1.7em; + padding: 10px 0;;// 추가 + + >span { + display: block; + text-align: center; + + &:last-child {//추가 + padding-bottom: 10px; + border-bottom: 1px solid #888; + } + >a { + color: #000; + } + } + + + + } + .copyright { // 추가 + text-align: center; + } + } + } + }//end of ul + }//end of f_section + }//end of footer + */ + footer { + width: 100%; + height: auto; + background-color: #444; } + footer > .inner { + position: relative; + padding-top: 20px; + width: 100%; } + footer > .inner > h1 { + float: inherit; + margin: 0 auto 180px; + width: 200px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo_w.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 0%; } + footer > .inner > .f_left { + float: inherit; + margin: 0 auto; + width: 100%; + padding-top: 20px; } + footer > .inner > .f_left > ul { + width: 100%; } + footer > .inner > .f_left > ul > li { + width: 100%; } + footer > .inner > .f_left > ul > li > dl > dt { + display: none; + margin: 0 auto; + width: 100%; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + footer > .inner > .f_left > ul > li > dl > dd { + padding-left: 20px; + text-align: left; + margin-top: 8px; + font-size: 13px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > .f_left > ul > li > dl > dd > em { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a:hover { + text-decoration: none; } + footer > .inner > address { + border-top: 1px solid #666; + float: inherit; + margin: 10px auto; + width: 100%; } + footer > .inner > address > ul { + width: 100%; } + footer > .inner > address > ul > li { + width: 100%; + text-align: center; } + footer > .inner > address > ul > li:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); } + footer > .inner > address > ul > li:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); } + footer > .inner > address > ul > li:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); } + footer > .inner > address > ul > li > dl > dt { + display: none; } + footer > .inner > address > ul > li > dl > dd { + padding-left: 20px; + text-align: left; + margin-top: 6px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > address > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > address > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a:hover { + text-decoration: underline; } + footer > .inner > .f_nav { + position: absolute; + top: 75px; + float: inherit; + margin-top: 0px; + width: 100%; } + footer > .inner > .f_nav > ul > li { + width: 100%; + text-align: center; + float: inherit; + margin-right: 0px; + padding-right: 0px; + background-image: none; + background-repeat: no-repeat; + background-position: 100% 73%; + border-top: 1px solid #666; } + footer > .inner > .f_nav > ul > li:last-child { + margin-right: none; + background-image: none; + border-bottom: 1px solid #666; } + footer > .inner > .f_nav > ul > li > a { + display: block; + height: 35px; + line-height: 35px; + font-size: 13px; + color: #fff; } + footer > .inner > .copyright { + border-top: 1px solid #666; + position: static; + padding: 20px 0; + top: 10px; + right: 50%; + transform: translateX(0); + width: 100%; + font-size: 13px; + letter-spacing: 1px; + text-align: center; + color: #fff; } + footer > .inner:after { + display: none; } + + footer > .inner > .snsBox{ + position: static; + margin: 0 auto; + text-align: center; + border-top: 1px solid #666; } + footer > .inner > .snsBox > ul > li:nth-child(1) a { + width: 30px; + height: 30px; + font-size: 13px; + color: #fff; + background: url('../images/footer_ico/youtube.png') no-repeat; + background-size: 30px; + display: inline-block; } } +/*# sourceMappingURL=layout.css.map */ diff --git a/css/layout.css.map b/css/layout.css.map new file mode 100644 index 0000000..53bd1c1 --- /dev/null +++ b/css/layout.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["layout.scss"], +"names": [], +"file": "layout.css" +} \ No newline at end of file diff --git a/css/layout.scss b/css/layout.scss new file mode 100644 index 0000000..4d6698a --- /dev/null +++ b/css/layout.scss @@ -0,0 +1,1128 @@ +@mixin innerSet ( $width, $margin){ + width : $width; + margin : $margin; +} + +.popup { + position: fixed; + top: 200px; + left: 200px; + width: 400px; + height: 300px; + background: url(../images/pop.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + z-index: 999999999999; + + p { + cursor: pointer; + position: absolute; + text-align: right; + bottom: 0px; + width: 100%; + color: #fff; + font-size: 20px; + font-weight: 600; + background: #0061a9; + } +} + + +.wrap { + width: 100%; +} + +section { + padding-top: 61px; +}//상단 헤더 높이 결정 요소 + +.fxContainer { + position: fixed; + width: 100%; + z-index: 999999; + + + + +header { + display: none; + width: 100%; + padding-left: 390px; + background-color: #fff; + border-bottom: 1px solid #dddddd; + + >.inner { + + >ul { + width: 200px; + margin-left : 25px; + border: 1px solid #dddddd; + border-top: none; + border-bottom: none; + + >li { + float: left; + width : 50%; + height: 35px; + line-height: 35px; + text-align: center; + + >a { + font-size: 12px; + color: #999999; + } + + >a:hover { + color: #333333; + } + } + }//end of header ul + }//end of inner + + +}//end of header +/*header 끝*/ + +nav { + background-color: #fff; + width: 100%; + height: 60px; + border-bottom : 1px solid #dddddd; + + + + >.inner { + position: relative; + width: 1200px; + margin : 0 auto; + + >.logo { + float: left; + width: 130px; + margin-left: 40px; + text-indent: -99999px; + + >a { + display: block; + height: 50px; + background: url(../images/BULE.png); + background-repeat: no-repeat; + background-position: 50% 100%; + background-size: contain; + + } + }//end of logo + + >ul { + float:right; + width: 810px; + //background-color: coral; + + >li { + position: relative; + float: left; + width: 20%; + line-height: 60px; + text-align: left; + + &:nth-child(1) ul { + height: 145px; + }// company ul + + &:nth-child(2) ul { + height: 145px; + }// industries ul + + &:nth-child(3){ + width:25%; + + + ul { + margin: 0 auto; + width: 100%; + height: 145px; + letter-spacing: -1px; + text-align: left; + >li { + a { + //padding-left: 5px; + } + } + + }// R&D ul + } + + &:nth-child(4) { + width: 25%; + }// industries ul + + &:nth-child(5) { + width : 5%; + font-weight: 900; + + >a { + color: #ddd; + transition: color 0.3s; + + &:hover { + color: #0061a9; + } + } + + } + + + >.point { + position: absolute; + top: 56px; + left: 0%; + //transform: translateX(-50%); + width: 2%; + height: 5px; + background-color: #0061a9; + content: ''; + } + + >a { + display: block; + height: 60px; + font-size: 14px; + color: #333333; + } + + >ul { + display: none; + width: 100%; + transition: 0.8s; + //background-color: coral; + + + + >li { + line-height: 35px; + text-align: left; + padding-left: 0px; + + >a { + display: block; + color: #666; + width: 100%; + font-size: 13px; + font-weight: 500; + + &:hover { + color: #0061a9; + font-weight: 700; + text-decoration: underline; + } + } + } + } + } + }//end of nav > inner > ul + + + + }//end of inner + >.language { + float: right; + width: 50px; + background-color: red; + + } + + >.subMenuBg { + display: none; + position: absolute; + top: 60px; + left: 0; + width: 100%; + height: 145px; + border-bottom: 1px solid #d7d7d7; + background-color: #fff; + opacity: 0.95; + z-index: -1; + }//end of subMenuBg + +}//end of nav + +} + + +/*nav 끝*/ +/* +footer { + width: 100%; + //height: 170px; + background-color: #f1f1f1; + + >.inner { + width: 1200px; + position: relative; + padding-top: 20px; + //margin: 0 auto; + + >ul { + padding-top: 20px; + + >li { + float: left; + margin-right: 30px; + text-align: center; + font-size: 16px; + + >ul { + padding: 10px 0 20px; + + >li { + text-align: center; + font-size: 14px; + line-height: 40px; + + >a { + color: #999; + } + } + } + + &:last-child { + margin-right: 0; + } + } + }//end of ul + }//end of inner + + >.f_section { + width: 100%; + border-top: 1px solid #ddd; + padding: 20px 0; + + >ul { + width: 1200px; + margin: 0 auto; + + li { + float: left; + >img { + width: 160px; + } + + >dl { + color: #000; + dt { + line-height: 1.7em; + + >em { + color: #0061a9; + font-weight: 600; + } + + } + + dd { + line-height: 1.7em; + >span { + >em { + color: #0061a9; + font-weight: 600; + } + >a { + color: #000; + } + } + + } + } + } + }//end of ul + }//end of f_section +}//end of footer +*/ +footer { + width: 100%; + height: 170px; + background-color: #444; + + >.inner { + //background-color: pink; + position: relative; + width : 1200px; + margin: 0 auto; + padding-top: 20px; + + >h1 { + float: left; + margin-left: 40px; + width: 130px; + height: 50px; + text-indent: -99999px; + background-image: url(../images/logo_w.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + }//end of h1 + + >.f_left { + float: left; + margin-left: 50px; + //background-color: pink; + + >ul { + width: 280px; + // background-color: red; + + > li { + + width: 400px; + //background-color: pink; + text-align: center; + + + >dl { + >dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + + }//end of dt + >dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + //font-weight: 700; + line-height: 1.2em; + color: #fff; + + >em { + color: #909090; + } + + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: underline; + } + + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of f_left + + >address { + float: left; + margin-top: 0px; + margin-left: 30px; + width: 340px; + //background-color: green; + + >ul { + width: 350px; + // background-color: red; + + > li { + + width: 320px; + //background-color: pink; + text-align: center; + + &:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + + }//end of dt + >dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; + //font-weight: 600; + + &:nth-child(2) { + // font-weight: 600; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: underline; + } + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of address + + >.f_nav { + float: right; + margin-top: 0px; + width: 270px; + //background-color: blue; + + >ul { + + >li { + width:calc(270px/5+ (9*5)); + float: left; + text-align: right; + margin-right: 9px; + //padding-right: 11px; + background-image: url(../images/f_right.png); + background-repeat: no-repeat; + background-position: 100% 73%; + + + + &:last-child { + margin-right: none; + background-image: none; + } + + >a { + + font-size: 13px; + color: #fff; + + + } + } + } + + } + + >.copyright { + position: absolute; + top: 120px; + right: -140px; + transform: translateX(-50%); + width: 315px; + font-size: 13px; + letter-spacing: 1px; + color: #fff; + + }//end of copyright + + &:after { + position: absolute; + top: 30px; + left: 200px; + transform: translateX(-50%); + width: 1px; + height: 120px; + background-color: #808080; + content: ''; + }//end of inner:after 하단 1자 선(상호) + + + }//end of inner + }//end of footer + +/*footer 끝*/ + + +/* +*************************************************************************** +RW 적용 CSS**************************************************************** +*************************************************************************** +*/ + +@media screen and (max-width:768px) { + + .toggleActive { + background-image: url(../images/toggle_cls.png) !important; + }//추가 + + .toggleActiveSub { + display: block !important; + } + + .fxContainer { + position: fixed; + width: 100%; + z-index: 999999; + + >.mobileToggle { + cursor: pointer; + position: absolute; + top: 0; + right: 0; + width: 100px; + height: 60px; + background-image: url(../images/toggle.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 70%; + z-index: 9999999; + + }//end of mobileToggle + + + + header { + display: none; + width: 100%; + padding-left: 390px; + background-color: #fff; + border-bottom: 1px solid #dddddd; + + >.inner { + + >ul { + width: 200px; + margin-left : 25px; + border: 1px solid #dddddd; + border-top: none; + border-bottom: none; + + >li { + float: left; + width : 50%; + height: 35px; + line-height: 35px; + text-align: center; + + >a { + font-size: 12px; + color: #999999; + } + + >a:hover { + color: #333333; + } + } + }//end of header ul + }//end of inner + + + }//end of header + /*header 끝*/ + + nav { + //background-color: #fff; + width: 100%; + height: 60px; + border-bottom : 1px solid #dddddd; + + >.inner { + position: relative; + width: 100%;//1200px + height: 100%;//추가 + margin : 0 auto;//0 auto + + >.logo { + float: left; + width: 130px; + margin-left: 0px; + text-indent: -99999px; + + >a { + display: block; + margin-top: 10px; + height: 40px; + background: url(../images/BULE.png); + background-repeat: no-repeat; + background-position: 80% -50%; + background-size: cover; + + } + }//end of logo + + >ul { + display: none;//추가 + float:right; + margin-top: 11px; + width: 100%;//550px + + >li { + position: relative; + float: inherit;//left + width: 100%;//25% + line-height: 60px; + text-align: center; + background-color: #666;// 추가 + border-bottom: 1px solid #444; + + &:nth-child(1) ul { + height: auto;//190px + }// company ul + + &:nth-child(2) ul { + height: auto;//190px + }// industries ul + + &:nth-child(3) { + width: 100%; + + >ul { + width: 100%;; + height: auto;//190px + text-align: center; + text-align-last: inherit; + letter-spacing: 0px; + } + }// R&D ul + + &:nth-child(4) { + width: 100%; + } + &:last-child { + width: 100%; + } + + >.point { + position: absolute; + top: 56px; + left: 50%; + transform: translateX(-50%); + width: 0%; + height: 5px; + background-color: #0061a9; + content: ''; + } + + >a { + display: block; + height: 60px; + color: #fff; + } + + >ul { + display: none; + width: 100%; + transition: 0.8s; + + + + >li { + display: none; + text-align: center; + line-height: 45px; + background-color: #ddd; + border-bottom: 1px solid #bbb; + + >a { + display: block; + color: #666; + font-size: 14px; + font-weight: 00; + + &:hover { + color: #0061a9; + font-weight: 500; + } + } + } + } + } + }//end of nav > inner > ul + + }//end of inner + + >.subMenuBg { + display: none; + position: absolute; + top: 60px; + left: 0; + width: 100%; + height: 190px; + border-bottom: 1px solid #d7d7d7; + background-color: #fff; + opacity: 0.95; + z-index: -1; + }//end of subMenuBg + + }//end of nav + + }//end of fxContainer 768px +/* + footer {// end of footer 768px + width: 100%; + background-color: #f1f1f1; + + >.inner { + width: 100%; // 1200px + margin: 0 auto; + + >ul { + padding-top: 20px; + + >li { + float: inherit; //left + margin-right: 0px;//30px + text-align: center; + font-size: 16px; + + >ul { + padding: 10px 0 20px; + + >li { + text-align: center; + font-size: 14px; + line-height: 40px; + + >a { + color: #999; + } + } + } + + &:last-child { + margin-right: 0; + } + } + }//end of ul + }//end of inner + + >.f_section { + width: 100%; + border-top: 1px solid #ddd; + padding: 20px 0; + + >ul { + width: 100%;//1200px + margin: 0 auto; + + li { + float: inherit; + + >img { + display: block; + width: 160px; + margin: 0 auto; + } + + >dl { + padding: 0 0px;// 0 25px + dt { + line-height: 1.7em; + border-bottom: 1px solid #888;//추가 + padding: 0px 25px 10px;//추가 + + } + + dd { + line-height: 1.7em; + padding: 10px 0;;// 추가 + + >span { + display: block; + text-align: center; + + &:last-child {//추가 + padding-bottom: 10px; + border-bottom: 1px solid #888; + } + >a { + color: #000; + } + } + + + + } + .copyright { // 추가 + text-align: center; + } + } + } + }//end of ul + }//end of f_section + }//end of footer +*/ + +footer { + width: 100%; + height: auto; + background-color: #444; + + >.inner { + //background-color: pink; + position: relative; + padding-top: 20px; + width: 100%;// 추가 + + >h1 { + float: inherit; + //margin-left: 0px;제거 + margin: 0 auto 180px;//추가 + width: 200px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo_w.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 0%; + }//end of h1 + + >.f_left { + float: inherit; + // margin-left: 50px; + margin: 0 auto; + width: 100%;//추가 + padding-top: 20px; + //background-color: pink; + + >ul { + width: 100%;//변경 + //background-color: red; + + > li { + + width: 100%;//변경 + //background-color: pink; + //text-align: center; + + &:nth-child(1) dl dt { + // background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + //background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + //background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + display: none; + margin: 0 auto; + width: 100%; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + + }//end of dt + >dd { + padding-left: 20px;//추가 + text-align: left;//변경 + margin-top: 8px; + font-size: 13px;//변경 + font-weight: 500; + line-height: 1.2em; + color: #fff; + + >em { + color: #909090; + } + + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: none;//변경 + } + + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of f_left + + >address { + border-top: 1px solid #666; + float: inherit;//변경 + // margin-top: 0px; + // margin-left: 30px; + margin: 10px auto; + width: 100%;//변경 + //background-color: green; + + >ul { + width: 100%; + // background-color: red; + + > li { + + width: 100%; + //background-color: pink; + text-align: center; + + &:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + display: none; + + + }//end of dt + >dd { + padding-left: 20px; + text-align: left;//변경 + margin-top: 6px;//변경 + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: underline; + } + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of address + + >.f_nav { + position: absolute; + top: 75px; + float: inherit;//변경 + margin-top: 0px; + width: 100%;//변경 + //background-color: blue; + + >ul { + + >li { + width: 100%;//추가 + text-align: center;//추가 + float: inherit;//변경 + margin-right: 0px;//변경 + padding-right: 0px;//변경 + background-image: none;//변경 + background-repeat: no-repeat; + background-position: 100% 73%; + border-top: 1px solid #666; + + + + &:last-child { + margin-right: none; + background-image: none; + border-bottom: 1px solid #666; + } + + >a { + display: block; + height: 35px; + line-height: 35px; + font-size: 13px; + color: #fff; + //background-color: orange; + + + } + } + } + + } + + >.copyright { + border-top: 1px solid #666 ;//추가 + position: static; + padding: 20px 0; + top: 10px;//변경 + right: 50%;//변경 + transform: translateX(0); + width: 100%; + font-size: 13px; + letter-spacing: 1px; + text-align: center; + color: #fff; + //background-color: green; + + }//end of copyright + + &:after { + display: none; + + }//end of inner:after 하단 1자 선(상호) + + + }//end of inner + }//end of footer +}//end of media Query 768px \ No newline at end of file diff --git a/css/reset.css b/css/reset.css new file mode 100644 index 0000000..e2c0eb3 --- /dev/null +++ b/css/reset.css @@ -0,0 +1,48 @@ +@import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css); + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; + text-decoration: none; + list-style: none; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; + font-family: "Nanum Gothic", sans-serif; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/css/rnd.css b/css/rnd.css new file mode 100644 index 0000000..6cd63dc --- /dev/null +++ b/css/rnd.css @@ -0,0 +1,574 @@ +.subBanner { + width: 100%; + height: 200px; + background: url(../images/RND_b.jpg); + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 60%; } + +.active_fixBtn { + overflow: hidden; + width: 38px !important; + height: 28px !important; + background-color: #0061a9 !important; } + +.trn_anc { + transform: rotate(90deg) !important; } + +.fixMenu { + display: none; + position: fixed; + right: 10px; + top: 50%; + width: 315px; + height: 160px; + background-color: rgba(0, 0, 0, 0.4); + transition: 0.3s; } + .fixMenu > p { + cursor: pointer; + float: right; + margin-right: 5px; + padding-top: 10px; + width: 30px; + height: 20px; + transform: rotate(-90deg); + background-image: url(../images/anchor.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 50%; + transition: 0.2s; } + .fixMenu > p:hover { + background-position: 50% 100%; } + .fixMenu > ul { + margin-top: 7px; } + .fixMenu > ul > li { + overflow: hidden; + position: relative; + width: 100%; + margin-top: 2px; + border-bottom: 1px solid rgba(255, 255, 255, 0.4); } + .fixMenu > ul > li:last-child { + border-bottom: none; } + .fixMenu > ul > li > a { + display: block; + width: 100%; + height: 30px; + line-height: 30px; + font-size: 13px; + padding-left: 25px; + color: #fff; + transition: 0.2s; } + .fixMenu > ul > li > a:hover { + background-color: #0061a9; } + .fixMenu > ul > li > a:after { + position: absolute; + top: 0px; + left: 10px; + width: 30px; + height: 30px; + transform: translateX(-50%) rotate(-90deg); + background-image: url(../images/anchor.png); + background-size: 50%; + background-repeat: no-repeat; + background-position: 50% 50%; + border-radius: 30px; + display: block; + height: 30px; + content: ''; } + +.rndContainer { + width: 100%; } + .rndContainer > p { + display: none; } + .rndContainer > ol { + display: none; } + .rndContainer > ul { + width: 1200px; + margin: 0px auto; } + .rndContainer > ul > li { + text-align: center; } + .rndContainer > ul > li:nth-child(1) { + position: relative; + width: 1200px; + margin: 80px auto 0; + text-align: center; + font-size: 50px; + font-weight: 600; + color: #000; + text-transform: uppercase; } + .rndContainer > ul > li:nth-child(1):after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left: -50px; + height: 5px; + background-color: #000; + content: ""; } + .rndContainer > ul > li:nth-child(2) { + padding-top: 40px; + font-size: 20px; + line-height: 2.5em; } + .rndContainer > .rndWrapper { + height: 1000px; } + .rndContainer > .rndWrapper > div { + position: relative; + width: 100%; + height: 800px; + background-repeat: no-repeat; + background-size: cover; } + .rndContainer > .rndWrapper > div > ul { + position: relative; + width: 1200px; + margin: 50px auto 0; } + .rndContainer > .rndWrapper > div > ul > li { + float: left; } + .rndContainer > .rndWrapper > div > ul > li:first-child { + overflow: hidden; + margin-right: 30px; + width: 570px; + height: 400px; + background-position: 50% 50%; + background-repeat: no-repeat; } + .rndContainer > .rndWrapper > div > ul > li:first-child > img { + width: 100%; + height: 100%; } + .rndContainer > .rndWrapper > div > ul > li:first-child > video { + width: 100%; + height: 100%; + background-color: #000; } + .rndContainer > .rndWrapper > div > ul > li:last-child { + width: 600px; + height: 400px; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl { + position: relative; + padding-top: 20px; + color: #fff; + z-index: 0; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl:after { + position: absolute; + top: 0px; + left: -15px; + width: 620px; + height: 400px; + background-color: rgba(0, 0, 0, 0.7); + content: ''; + z-index: -1; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dt { + margin-top: 20px; + font-weight: 600; + font-size: 23px; + z-index: 1; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd { + margin: 20px 0 40px; + line-height: 1.3em; + font-size: 16px; + letter-spacing: 1px; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd > ul > li { + margin-right: 20px; + width: 180px; + float: left; + height: 120px; + box-sizing: border-box; + cursor: pointer; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd > ul > li:first-child { + border: 3px solid orange; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd > ul > li > img { + width: 100%; + height: 100%; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd > ul > li > video { + cursor: pointer; + width: 100%; + height: 100%; } + .rndContainer > .rndWrapper > div > .rndInfo { + width: 1200px; + height: 450px; + margin: 50px auto 0; + background-color: rgba(0, 0, 0, 0.7); + overflow-y: scroll; } + .rndContainer > .rndWrapper > div > .rndInfo::-webkit-scrollbar { + width: 8px; + height: 8px; + border: 1px solid #fff; } + .rndContainer > .rndWrapper > div > .rndInfo::-webkit-scrollbar-track { + background: #efefef; + -webkit-border-radius: 10px; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.2); } + .rndContainer > .rndWrapper > div > .rndInfo::-webkit-scrollbar-thumb { + height: 50px; + width: 50px; + background: rgba(0, 0, 0, 0.2); + -webkit-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.1); } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll { + width: 100%; + height: auto; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul { + padding: 30px 20px; + font-size: 16px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul:first-child { + padding-top: 50px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > li { + color: #fff; + line-height: 1.7em; + margin-bottom: 20px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceTitle { + margin-bottom: 10px; + font-size: 21px; + font-weight: 600; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceImg > span { + width: 1000px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceImg > span > img { + width: 80%; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceHandle { + width: 1150px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceHandle > dl { + margin-right: 30px; + width: 350px; + float: left; + padding-top: 30px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceHandle > dl > dd > img { + width: 90%; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceHandle > dl > dd:last-child { + height: 50px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceChart > dl { + margin-top: 10px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceChart > dl > dt { + font-weight: 600; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceChart > dl > dd { + padding-left: 25px; } + .rndContainer > .rndWrapper > .deepLearning { + height: 100%; + background-image: url(../images/car1_w.jpg); + background-size: cover; + background-position: 50% 50%; + background-repeat: no-repeat; } + .rndContainer > .rndWrapper > .lunarSystem { + height: 100%; + background-image: url(../images/moon_w.jpg); + background-size: cover; + background-position: 50% 30%; } + .rndContainer > .rndWrapper > .LiquefactionModule { + height: 100%; + background-image: url(../images/disaster_w.jpg); + background-position: 50% 60%; + background-size: cover; } + .rndContainer > .rndWrapper > .koreaRoadSign { + height: 100%; + background-image: url(../images/road_w.jpg); + background-position: 50% 30%; } + .rndContainer > .rndWrapper > .koreaRoadSign > ul > li:nth-child(2) > dl > dd > a { + color: orange; + font-weight: 600; } + .rndContainer > .rndWrapper > .koreaRoadSign:after { + display: none; } + +@keyframes anchor { + from { + bottom: 50px; } + to { + bottom: 15px; } } +@media screen and (max-width: 768px) { + .subBanner { + width: 100%; + height: 250px; + background: url(../images/RND_m.png); + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; } + + .fixMenu { + display: none; + position: fixed; + right: 10px; + top: inherit; + bottom: 50%; + width: 315px; + height: 160px; + background-color: rgba(0, 0, 0, 0.4); + transition: 0.3s; } + .fixMenu > p { + cursor: pointer; + float: right; + margin-right: 5px; + padding-top: 10px; + width: 30px; + height: 20px; + transform: rotate(-90deg); + background-image: url(../images/anchor.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 50%; + transition: 0.2s; } + .fixMenu > p:hover { + background-position: 50% 100%; } + .fixMenu > ul { + margin-top: 7px; } + .fixMenu > ul > li { + overflow: hidden; + position: relative; + width: 100%; + margin-top: 2px; + border-bottom: 1px solid rgba(255, 255, 255, 0.4); } + .fixMenu > ul > li:last-child { + border-bottom: none; } + .fixMenu > ul > li > a { + display: block; + width: 100%; + height: 30px; + line-height: 30px; + font-size: 13px; + padding-left: 25px; + color: #fff; + transition: 0.2s; } + .fixMenu > ul > li > a:hover { + background-color: #0061a9; } + .fixMenu > ul > li > a:after { + position: absolute; + top: 0px; + left: 10px; + width: 30px; + height: 30px; + transform: translateX(-50%) rotate(-90deg); + background-image: url(../images/anchor.png); + background-size: 50%; + background-repeat: no-repeat; + background-position: 50% 50%; + border-radius: 30px; + display: block; + height: 30px; + content: ''; } + + .rndContainer { + position: relative; + height: auto; } + .rndContainer > p { + display: block; } + .rndContainer > ol { + display: block; } + .rndContainer > p { + position: absolute; + top: 15px; + right: 30px; + z-index: 9999; } + .rndContainer > p > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .rndContainer > ol { + position: absolute; + top: 15px; + right: 20px; + z-index: 9999; } + .rndContainer > ol > li { + float: left; } + .rndContainer > ol > li > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .rndContainer > ul { + width: 100%; + margin: 100px auto; } + .rndContainer > ul > li { + text-align: center; } + .rndContainer > ul > li:nth-child(1) { + position: relative; + width: 100%; + margin: 80px auto 0; + text-align: center; + font-size: 30px; + font-weight: 600; + color: #000; + text-transform: uppercase; } + .rndContainer > ul > li:nth-child(1):after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left: -50px; + height: 3px; + background-color: #000; + content: ""; } + .rndContainer > ul > li:nth-child(2) { + padding-top: inherit; + padding: 40px 20px; + font-size: 14px; + line-height: 2.5em; } + .rndContainer > .rndWrapper { + height: 1200px; } + .rndContainer > .rndWrapper > div { + position: relative; + height: 1200px; + width: 100%; + background-repeat: no-repeat; + background-size: cover; } + .rndContainer > .rndWrapper > div:after { + display: none; + position: absolute; + bottom: 50px; + left: 50%; + transform: translateX(-50%); + width: 30px; + height: 30px; + background: url(../images/anchor.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; + animation-name: anchor; + animation-duration: 1s; + animation-iteration-count: infinite; } + .rndContainer > .rndWrapper > div > ul { + position: relative; + width: 100%; + margin: 100px auto 0; } + .rndContainer > .rndWrapper > div > ul > li { + float: inherit; + text-align: center; } + .rndContainer > .rndWrapper > div > ul > li:first-child { + overflow: hidden; + padding-top: 300px; + margin-right: 30px; + width: 100%; + height: 400px; + background-position: 50% 50%; + background-repeat: no-repeat; } + .rndContainer > .rndWrapper > div > ul > li:first-child > img { + width: 100%; + height: 70%; } + .rndContainer > .rndWrapper > div > ul > li:first-child > video { + width: 100%; + height: 70%; } + .rndContainer > .rndWrapper > div > ul > li:last-child { + position: absolute; + top: -70px; + width: 100%; + height: 400px; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl { + position: relative; + padding-top: 20px; + color: #fff; + z-index: 0; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl:after { + position: absolute; + top: -10px; + left: 50%; + transform: translateX(-50%); + width: 100%; + height: 110%; + background-color: rgba(0, 0, 0, 0.7); + content: ''; + z-index: -1; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dt { + margin-top: 20px; + font-weight: 600; + font-size: 19px; + z-index: 1; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd { + margin: 20px 0 40px; + line-height: 1.9em; + font-size: 14px; + letter-spacing: 1px; + text-align: left; + padding: 0 20px; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd:last-child { + position: absolute; + bottom: -150px; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd > ul > li { + cursor: pointer; + margin-left: 0px; + margin-right: 0px; + width: 33.333333%; + float: left; + height: 80px; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd > ul > li > img { + width: 100%; + height: 100%; } + .rndContainer > .rndWrapper > div > ul > li:last-child > dl > dd > ul > li > video { + width: 100%; + height: 100%; } + .rndContainer > .rndWrapper > div > .rndInfo { + width: 100%; + height: 410px; + margin: -80px auto 0; + background-color: rgba(0, 0, 0, 0.7); + overflow-y: scroll; } + .rndContainer > .rndWrapper > div > .rndInfo::-webkit-scrollbar { + width: 8px; + height: 8px; + border: 1px solid #fff; } + .rndContainer > .rndWrapper > div > .rndInfo::-webkit-scrollbar-track { + background: #efefef; + -webkit-border-radius: 10px; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.2); } + .rndContainer > .rndWrapper > div > .rndInfo::-webkit-scrollbar-thumb { + height: 50px; + width: 50px; + background: rgba(0, 0, 0, 0.2); + -webkit-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.1); } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll { + width: 100%; + height: auto; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul { + padding: 50px 20px; + font-size: 16px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > li { + color: #fff; + line-height: 1.7em; + font-size: 14px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceTitle { + font-size: 17px; + font-weight: 600; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceImg > span { + width: 100%; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceImg > span > img { + width: 100%; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceHandle { + width: 100%; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceHandle > dl { + margin-right: 30px; + width: 350px; + float: left; + padding-top: 30px; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceHandle > dl > dd > img { + width: 90%; } + .rndContainer > .rndWrapper > div > .rndInfo > .innerScroll > ul > .techIntroduceHandle > dl > dd:last-child { + line-height: 1.2em; } + .rndContainer > .rndWrapper > .deepLearning { + background: #555; + background-position: 50% 30%; } + .rndContainer > .rndWrapper > .deepLearning > ul > li:last-child > dl > dd:last-child { + bottom: -170px; } + .rndContainer > .rndWrapper > .deepLearning > ul > li:last-child > dl > dd:last-child > ul li { + height: 100px; } + .rndContainer > .rndWrapper > .deepLearning > ul > li:last-child > dl > dd:last-child > ul li > img { + height: 100px; } + .rndContainer > .rndWrapper > .lunarSystem { + background-image: url(../images/moon.jpg); + background-position: 50% 30%; } + .rndContainer > .rndWrapper > .LiquefactionModule { + background-image: url(../images/module.jpg); + background-position: 50% 90%; + background-size: cover; } + .rndContainer > .rndWrapper > .LiquefactionModule > ul > li:nth-child(1) { + padding-top: 340px; } + .rndContainer > .rndWrapper > .koreaRoadSign { + background-image: url(../images/road.jpg); + background-position: 50% 30%; } + .rndContainer > .rndWrapper > .koreaRoadSign > ul > li:nth-child(1) { + padding-top: 370px; } + .rndContainer > .rndWrapper > .koreaRoadSign:after { + display: none; } } + +/*# sourceMappingURL=rnd.css.map */ diff --git a/css/rnd.css.map b/css/rnd.css.map new file mode 100644 index 0000000..430c006 --- /dev/null +++ b/css/rnd.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["rnd.scss"], +"names": [], +"file": "rnd.css" +} \ No newline at end of file diff --git a/css/rnd.scss b/css/rnd.scss new file mode 100644 index 0000000..34e1a65 --- /dev/null +++ b/css/rnd.scss @@ -0,0 +1,1049 @@ +.subBanner { + width: 100%; + height: 200px; + background: url(../images/RND_b.jpg) ; + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 60%; + +}//end of subBanner + +.active_fixBtn { + overflow: hidden; + width : 38px !important; + height: 28px !important; + background-color: #0061a9 !important;; + +} + +.trn_anc { + transform: rotate(90deg) !important; +} + +.fixMenu { + display: none; + position: fixed; + right: 10px; + top: 50%; + width: 315px; + height: 160px; + background-color: rgba(000,000,000,0.4); + transition: 0.3s; + + + + >p { + cursor: pointer; + float: right; + margin-right: 5px; + padding-top : 10px; + width: 30px; + height: 20px; + transform: rotate(-90deg); + background-image: url(../images/anchor.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 50%; + transition: 0.2s; + + &:hover { + background-position: 50% 100%; + } + } + + >ul { + margin-top: 7px; + + >li { + overflow: hidden; + position: relative; + width: 100%; + margin-top: 2px; + border-bottom: 1px solid rgba(255,255,255,0.4); + + &:last-child { + border-bottom: none; + } + + >a { + + display: block; + width: 100%; + height: 30px; + line-height: 30px; + font-size: 13px; + padding-left: 25px; + color: #fff; + transition : 0.2s; + + &:hover { + background-color: #0061a9; + } + + + &:after { + position: absolute; + top: 0px; + left: 10px; + width: 30px; + height: 30px; + transform: translateX(-50%) rotate(-90deg); + background-image: url(../images/anchor.png); + background-size: 50%; + background-repeat: no-repeat; + background-position: 50% 50%; + border-radius: 30px; + display: block; + height: 30px; + content: ''; + + } + } + + } + } +} + + + + +.rndContainer { + width: 100%; + + >p { + display: none; + } + + >ol { + display: none; + } + + + >ul { + width: 1200px; + margin: 0px auto; + + >li { + text-align: center; + + &:nth-child(1) { + position: relative; + width: 1200px; + margin: 80px auto 0; + text-align: center; + font-size: 50px; + font-weight: 600; + color: #000; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left : -50px; + height: 5px; + background-color: #000; + content: ""; + } + } + + &:nth-child(2) { + padding-top: 40px; + font-size: 20px; + line-height: 2.5em; + } + + } + }//end of ul + + + >.rndWrapper { + height: 1000px; + + + >div { + position: relative; //all achor relative + width: 100%; + height: 800px; + background-repeat: no-repeat; + background-size: cover; + + + + + + >ul { + position: relative; + width: 1200px; + margin: 50px auto 0; + + >li { + float: left; + + &:first-child { + overflow: hidden; + margin-right: 30px; + width: 570px; + height: 400px; + background-position: 50% 50%; + background-repeat: no-repeat; + + >img { + width: 100%; + height: 100%; + } + + >video { + width: 100%; + height: 100%; + background-color: #000; + } + + + + } + + &:last-child { + width: 600px; + height: 400px; + + >dl { + position: relative; + padding-top: 20px; + color: #fff; + z-index: 0; + + &:after { + position: absolute; + top: 0px; + left: -15px; + width: 620px; + height: 400px; + background-color: rgba(000,000,000,0.7); + content: ''; + z-index: -1; + } + + >dt { + margin-top: 20px; + font-weight: 600; + font-size: 23px; + z-index: 1; + + } + >dd { + margin: 20px 0 40px; + line-height: 1.3em; + font-size: 16px; + letter-spacing: 1px; + + >ul { + + >li { + margin-right: 20px; + width: 180px; + float: left; + height: 120px; + //background-size: cover; + //background-repeat: no-repeat; + //background-position: 50% 50%; + box-sizing: border-box; + cursor: pointer; + + &:first-child { + border: 3px solid orange; + } + + >img { + width: 100%; + height: 100%; + } + + >video { + cursor: pointer; + width: 100%; + height: 100%; + } + + + + } + } + + } + } + }//end of 설명 부분 li + + + }//end of li + } + + + >.rndInfo { + width: 1200px; + height: 450px; + margin: 50px auto 0; + background-color: rgba(000,000,000,0.7); + overflow-y: scroll; + + &::-webkit-scrollbar { + width: 8px; + height: 8px; + border: 1px solid #fff; + }//스크롤 관련 css + &::-webkit-scrollbar-track {background: #efefef; + -webkit-border-radius: 10px; + border-radius:10px; + -webkit-box-shadow: inset 0 0 4px rgba(0,0,0,.2); + }//스크롤 관련 css + + &::-webkit-scrollbar-thumb { + height: 50px; + width: 50px; + background: rgba(0,0,0,.2); + -webkit-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: inset 0 0 4px rgba(0,0,0,.1); + }//스크롤 관련 css + + + >.innerScroll { + width: 100%; + height: auto; + + >ul { + padding: 30px 20px; + font-size: 16px; + + &:first-child { + padding-top: 50px; + } + + >li { + color: #fff; + line-height: 1.7em; + margin-bottom: 20px; + + } + + >.techIntroduceTitle { + margin-bottom: 10px; + font-size: 21px; + font-weight: 600; + + } + + >.techIntroduceImg { + >span { + width: 1000px; + >img { + width: 80%; + } + } + }//end of techIntroduceImg + >.techIntroduceHandle { + width: 1150px; + //background-color: orange; + >dl { + margin-right: 30px; + width: 350px; + float: left; + padding-top: 30px; + + >dd { + >img { + width: 90%; + } + + &:last-child { + height: 50px; + //background-color: orange; + //line-height: 1.2em; + } + } + } + }//end of techIntroduceHandle + + >.techIntroduceChart { + >dl { + margin-top: 10px; + + >dt { + font-weight: 600; + } + + >dd { + padding-left: 25px; + } + } + }//end of techIntroduceImg + } + + }//end of innerScroll + }//end of rndInfo + + + + + }//end of all div layout + + >.deepLearning { + height: 100%; + background-image: url(../images/car1_w.jpg); + background-size: cover; + background-position: 50% 50%; + background-repeat: no-repeat; + + + + }//end of deepLearning + + >.lunarSystem { + height: 100%; + background-image: url(../images/moon_w.jpg); + background-size: cover; + background-position: 50% 30%; + + }//end of lunarSystem + + >.LiquefactionModule { + height: 100%; + background-image: url(../images/disaster_w.jpg); + //background-color: gray; + background-position: 50% 60%; + background-size: cover; + + }//end of LiquefactionModule + + >.koreaRoadSign { + height: 100%; + background-image: url(../images/road_w.jpg); + background-position: 50% 30%; + + >ul { + >li { + + &:nth-child(1) { + //background-image: url(../images/korearoad_1.png); + } + + &:nth-child(2) { + + >dl > dd{ + + >a { + color: orange; + font-weight: 600; + } + + &:last-child { + + >ul>li { + + &:nth-child(1) { + + // background-image: url(../images/korearoad_2.png); + + } + + &:nth-child(2) { + + // background-image: url(../images/korearoad_3.png); + + } + + &:nth-child(3) { + + // background-image: url(../images/korearoad_3.png); + + } + + + } + } + } + } + + } + } + + + + &:after { + display: none; + + + } + + + }//end of koreaRoadSign + + }//end of rndWrapper +}//end of rndContainer + +@keyframes anchor { + from {bottom : 50px;} + to {bottom : 15px;} +} + + + + +@media screen and (max-width:768px) { + + .subBanner { + width: 100%; + height: 250px;//350px + background: url(../images/RND_m.png) ; + background-repeat: no-repeat; + background-size: cover; + background-position: 100% 50%; + + }//end of subBanner + + + .fixMenu { + display: none; + position: fixed; + right: 10px; + top: inherit;//50% + bottom : 50%; + width: 315px; + height: 160px; + background-color: rgba(000,000,000,0.4); + transition: 0.3s; + + + + >p { + cursor: pointer; + float: right; + margin-right: 5px; + padding-top : 10px; + width: 30px; + height: 20px; + transform: rotate(-90deg); + background-image: url(../images/anchor.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 50%; + transition: 0.2s; + + &:hover { + background-position: 50% 100%; + } + } + + >ul { + margin-top: 7px; + + >li { + overflow: hidden; + position: relative; + width: 100%; + margin-top: 2px; + border-bottom: 1px solid rgba(255,255,255,0.4); + + &:last-child { + border-bottom: none; + } + + >a { + + display: block; + width: 100%; + height: 30px; + line-height: 30px; + font-size: 13px; + padding-left: 25px; + color: #fff; + transition : 0.2s; + + &:hover { + background-color: #0061a9; + } + + + &:after { + position: absolute; + top: 0px; + left: 10px; + width: 30px; + height: 30px; + transform: translateX(-50%) rotate(-90deg); + background-image: url(../images/anchor.png); + background-size: 50%; + background-repeat: no-repeat; + background-position: 50% 50%; + border-radius: 30px; + display: block; + height: 30px; + content: ''; + + } + } + + } + } + }//end of fixMenu + + + + + .rndContainer { + position: relative; + height: auto; + + >p { + display: block; + } + + >ol { + display: block; + } + + >p { + position: absolute; + top: 15px; + right: 30px; + z-index: 9999; + + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + + } + + >ol { + position: absolute; + top:15px; + right: 20px; + z-index: 9999; + + >li { + float: left; + + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + } + + } + + >ul { + width: 100%;//1200px + margin: 100px auto; + + >li { + text-align: center; + + &:nth-child(1) { + position: relative; + width: 100%;//1200px + margin: 80px auto 0; + text-align: center; + font-size: 30px; + font-weight: 600; + color: #000; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left : -50px; + height: 3px; + background-color: #000; + content: ""; + } + } + + &:nth-child(2) { + padding-top: inherit;//40px + padding: 40px 20px; + font-size: 14px; + line-height: 2.5em; + } + + } + }//end of ul + + + >.rndWrapper { + height: 1200px; + + >div { + position: relative; //all achor relative + height: 1200px; + width: 100%; + background-repeat: no-repeat; + background-size: cover; + + &:after { + display: none; + position: absolute; + bottom: 50px; + left: 50%; + transform: translateX(-50%); + width: 30px; + height : 30px; + background: url(../images/anchor.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + content: ''; + animation-name: anchor; + animation-duration: 1s; + animation-iteration-count: infinite; + + + } + + + + >ul { + position: relative; + width: 100%;//1200px + margin: 100px auto 0; + + >li { + float: inherit;//left + text-align: center; + + &:first-child { + overflow: hidden; + padding-top: 300px;//추가 + margin-right: 30px; + width: 100%;//570px + height: 400px; + background-position: 50% 50%; + background-repeat: no-repeat; + + >img { + width: 100%; + height: 70%; + //z-index: 9999999; + } + + >video { + width: 100%; + height: 70%; + } + + + + } + + &:last-child { + position: absolute; + top: -70px; + width: 100%;//600px + height: 400px; + + >dl { + position: relative; + padding-top: 20px; + color: #fff; + z-index: 0; + + &:after { + position: absolute; + top: -10px; + left: 50%; + transform: translateX(-50%); + width: 100%;//620px + height: 110%;//400px + background-color: rgba(000,000,000,0.7);// 0.5 + content: ''; + z-index: -1; + } + + + + >dt { + margin-top: 20px; + font-weight: 600; + font-size: 19px; + z-index: 1; + + } + >dd { + margin: 20px 0 40px; + line-height: 1.9em; + font-size: 14px; + letter-spacing: 1px; + text-align: left;//추가 + padding: 0 20px;//추가 + + + + &:last-child {//추가 + position: absolute; + bottom: -150px; + + } + + + >ul { + + + >li { + cursor: pointer; + margin-left: 0px; + margin-right: 0px; + width: 33.333333%;// + float: left; + height: 80px; + //background-size: cover; + //background-repeat: no-repeat; + //background-position: 50% 50%; + + + + >img { + width: 100%; + height: 100%; + } + + >video { + + width: 100%; + height: 100%; + } + + + + } + } + + } + } + }//end of 설명 부분 li + + + }//end of li + } + + + >.rndInfo { + width: 100%;//1200px + height: 410px;//450px + margin: -80px auto 0;//30px auto 0 + background-color: rgba(000,000,000,0.7); + overflow-y: scroll; + + &::-webkit-scrollbar { + width: 8px; + height: 8px; + border: 1px solid #fff; + }//스크롤 관련 css + &::-webkit-scrollbar-track {background: #efefef; + -webkit-border-radius: 10px; + border-radius:10px; + -webkit-box-shadow: inset 0 0 4px rgba(0,0,0,.2); + }//스크롤 관련 css + + &::-webkit-scrollbar-thumb { + height: 50px; + width: 50px; + background: rgba(0,0,0,.2); + -webkit-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: inset 0 0 4px rgba(0,0,0,.1); + }//스크롤 관련 css + + + >.innerScroll { + width: 100%; + height: auto; + + >ul { + padding: 50px 20px; + font-size: 16px; + + >li { + color: #fff; + line-height: 1.7em; + font-size: 14px; + + } + + >.techIntroduceTitle { + font-size: 17px; + font-weight: 600; + } + + >.techIntroduceImg { + >span { + width: 100%; + >img { + width: 100%; + } + } + }//end of techIntroduceImg + >.techIntroduceHandle { + width: 100%; + //background-color: orange; + >dl { + margin-right: 30px; + width: 350px; + float: left; + padding-top: 30px; + + >dd { + >img { + width: 90%; + } + + &:last-child { + line-height: 1.2em; + } + } + } + } + } + + }//end of innerScroll + }//end of rndInfo + + + }//end of all div layout + + >.deepLearning { + background: #555; + //background-image: url(../images/car1.jpg); + background-position: 50% 30%; + + + >ul { + >li:last-child { + >dl{ + >dd:last-child{ + bottom: -170px; + >ul{ + li { + height: 100px; + + >img { + height: 100px; + } + } + } + } + } + } + } + + + }//end of deepLearning + + >.lunarSystem { + + background-image: url(../images/moon.jpg); + background-position: 50% 30%; + + }//end of lunarSystem + + >.LiquefactionModule { + + background-image: url(../images/module.jpg); + //background-color: gray; + background-position: 50% 90%; + background-size: cover; + + >ul { + >li { + + &:nth-child(1) { + padding-top: 340px; + } + } + } + + }//end of LiquefactionModule + + >.koreaRoadSign { + + background-image: url(../images/road.jpg); + background-position: 50% 30%; + + >ul { + >li { + + &:nth-child(1) { + padding-top: 370px; + } + + &:nth-child(2) { + + >dl > dd{ + + &:last-child { + + >ul>li { + + &:nth-child(1) { + + // background-image: url(../images/korearoad_2.png); + + } + + &:nth-child(2) { + + // background-image: url(../images/korearoad_3.png); + + } + + &:nth-child(3) { + + // background-image: url(../images/korearoad_3.png); + + } + + + } + } + } + } + + } + } + + + + &:after { + display: none; + + + } + + + }//end of koreaRoadSign + + }//end of rndWrapper + }//end of rndContainer + + + + + + +}//mediaQuery \ No newline at end of file diff --git a/css/status.css b/css/status.css new file mode 100644 index 0000000..010b859 --- /dev/null +++ b/css/status.css @@ -0,0 +1,141 @@ +.statusContainer { + position: relative; + width: 100%; + height: auto; + background: url(../images/map_2.png); + background-position: 50% 150%; + background-repeat: no-repeat; + background-size: contain; } + .statusContainer > ol { + position: absolute; + top: 30px; + right: 20px; + display: none; } + .statusContainer > ol > li { + float: left; } + .statusContainer > ol > li > a { + padding: 10px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; } + .statusContainer > p { + position: relative; + width: 100%; + margin: 80px auto 0; + text-align: center; + font-size: 23px; + font-weight: 600; + color: #000; } + .statusContainer > p:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left: -50px; + height: 5px; + background-color: #000; + content: ""; } + .statusContainer > .status { + margin-top: 100px; + width: 100%; } + .statusContainer > .status > .inner { + position: relative; + width: 1200px; + margin: 0 auto 20px; + border-top: 2px solid #ddd; } + .statusContainer > .status > .inner:last-child { + margin-bottom: 100px; } + .statusContainer > .status > .inner > .since { + position: absolute; + top: 20px; + left: 50px; + font-size: 35px; + font-weight: 600; + color: #0061a9; + content: "2018"; } + .statusContainer > .status > .inner > ul { + padding-top: 20px; + padding-left: 350px; + width: 800px; + margin: 0 auto; + text-align: left; + font-size: 17px; } + .statusContainer > .status > .inner > ul > li { + padding: 20px 0 10px; + border-bottom: 1px dashed #ccc; + line-height: 1.7em; } + .statusContainer > .status > .inner > ul > li > dl > dd > ul > li { + float: left; } + .statusContainer > .status > .inner > ul > li > dl > dd > ul > li:last-child { + margin-left: 10px; } + .statusContainer > .status > .inner > ul > li:last-child { + border-bottom: 0; } + +@media screen and (max-width: 768px) { + .statusContainer { + width: 100%; + height: auto; + background: url(../images/map_2.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + .statusContainer > ol { + display: block; } + .statusContainer > p { + position: relative; + width: 100%; + margin: 80px auto 0; + text-align: center; + font-size: 23px; + font-weight: 600; + color: #000; } + .statusContainer > p:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 50px; + margin-left: -25px; + height: 3px; + background-color: #000; + content: ""; } + .statusContainer > .status { + margin-top: 100px; + width: 100%; } + .statusContainer > .status > .inner { + position: relative; + width: 100%; + margin: 0 auto 20px; + border-top: 2px solid #ddd; } + .statusContainer > .status > .inner:last-child { + margin-bottom: 100px; } + .statusContainer > .status > .inner > .since { + position: absolute; + top: 20px; + left: 50%; + transform: translateX(-50%); + font-size: 50px; + font-weight: 600; + color: #0061a9; + content: "2018"; } + .statusContainer > .status > .inner > ul { + padding-top: 70px; + padding-left: 0px; + width: 100%; + margin: 0 auto; + text-align: left; + font-size: 15px; } + .statusContainer > .status > .inner > ul > li { + padding: 20px; + border-bottom: 1px dashed #ccc; + line-height: 1.5em; } + .statusContainer > .status > .inner > ul > li > dl > dd { + padding: 10px 0; + line-height: 1.3em; } + .statusContainer > .status > .inner > ul > li > dl > dd w { + display: none; } + .statusContainer > .status > .inner > ul > li:last-child { + border-bottom: 0; } } + +/*# sourceMappingURL=status.css.map */ diff --git a/css/status.css.map b/css/status.css.map new file mode 100644 index 0000000..14c78e0 --- /dev/null +++ b/css/status.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["status.scss"], +"names": [], +"file": "status.css" +} \ No newline at end of file diff --git a/css/status.scss b/css/status.scss new file mode 100644 index 0000000..533495a --- /dev/null +++ b/css/status.scss @@ -0,0 +1,238 @@ +.statusContainer { + position: relative; + width: 100%; + height: auto; + background: url(../images/map_2.png); + background-position: 50% 150%; + background-repeat: no-repeat; + background-size: contain; + + >ol { + position: absolute; + top: 30px; + right: 20px; + display: none; + + >li { + float: left; + + + >a { + padding: 10px; + //width: 40px; + //height: 40px; + text-align: center; + font-size: 30px; + font-weight: 900; + color: #333; + background-color: #ddd; + } + } + + } + + >p { + position: relative; + width: 100%; + margin: 80px auto 0; + text-align: center; + font-size: 23px; + font-weight: 600; + color: #000; + + &:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 100px; + margin-left : -50px; + height: 5px; + background-color: #000; + content: ""; + } + + }//end of p + + >.status { + margin-top: 100px; + width: 100%; + + >.inner { + position: relative;//2018 relative + width: 1200px; + margin: 0 auto 20px; + border-top: 2px solid #ddd; + + &:last-child { + margin-bottom: 100px; + } + + >.since { + position: absolute; + top: 20px; + left: 50px; + font-size: 35px; + font-weight: 600; + color: #0061a9; + content :"2018"; + } + + + + >ul { + padding-top: 20px; + padding-left: 350px; + width: 800px; + margin : 0 auto; + text-align: left; + font-size: 17px; + + + + + + >li { + padding: 20px 0 10px; + border-bottom: 1px dashed #ccc; + line-height: 1.7em; + + >dl { + + >dd { + + >ul{ + >li { + float: left; + + &:last-child { + margin-left: 10px; + } + } + } + } + } + + &:last-child { + border-bottom: 0; + } + } + + } + + }//end of inner + + }//end of status + +}//end of statusContainer + + + +@media screen and (max-width:768px) { + + + .statusContainer { + width: 100%; + height: auto; + background: url(../images/map_2.png); + background-position: 50% 50%;// 50% 150% + background-repeat: no-repeat; + background-size: cover;//contain + + >ol { + display: block; + + >li { + + } + } + + + + >p { + position: relative; + width: 100%; + margin: 80px auto 0; + text-align: center; + font-size: 23px; + font-weight: 600; + color: #000; + + &:after { + position: absolute; + bottom: -25px; + left: 50%; + width: 50px; + margin-left : -25px; + height: 3px; + background-color: #000; + content: ""; + } + + }//end of p + + >.status { + margin-top: 100px; + width: 100%; + + >.inner { + position: relative;//2018 relative + width: 100%;//1200px + margin: 0 auto 20px; + border-top: 2px solid #ddd; + + &:last-child { + margin-bottom: 100px; + } + + >.since { + position: absolute; + top: 20px; + left: 50%;//50px + transform: translateX(-50%); + font-size: 50px; + font-weight: 600; + color: #0061a9; + content :"2018"; + } + + + + >ul { + padding-top: 70px; + padding-left: 0px;//350px + width: 100%;//630px + margin : 0 auto; + text-align: left; + font-size: 15px; + + + >li { + padding: 20px; // 20px 0 + border-bottom: 1px dashed #ccc; + line-height: 1.5em; + + >dl { + >dd { + padding: 10px 0;//추가 + line-height: 1.3em; + + w { + display: none; + } + } + } + + &:last-child { + border-bottom: 0; + } + } + + } + + }//end of inner + + }//end of status + + }//end of statusContainer + +}//media Query \ No newline at end of file diff --git a/css/style.css b/css/style.css new file mode 100644 index 0000000..bf25372 --- /dev/null +++ b/css/style.css @@ -0,0 +1,730 @@ +@charset "UTF-8"; +.clearfix { + *zoom: 1; } + +.clearfix:after { + clear: both; + display: block; + content: ""; } + +.hidden { + text-indent: -99999px; + width: 0; + height: 0; } + +#wrap { + width: 100%; } + +/*기본 세팅*/ +section > .mainBanner { + overflow: hidden; + position: relative; + width: 100%; + height: 300px; + background-position: 50% 80%; + background-size: cover; + background-repeat: no-repeat; } + section > .mainBanner > .mainBannerCont { + width: 100%; } + section > .mainBanner > .mainBannerCont > .inner { + width: 100%; + height: 510px; } + section > .mainBanner > .mainBannerCont > .inner > ul > li { + position: absolute; + top: 0; + left: 0; + float: left; + height: 300px; + width: 100%; + text-align: center; } + section > .mainBanner > .mainBannerCont > .inner > ul > li:nth-child(1) { + background-image: url(../images/banner_01.png); + background-position: 50% 0%; } + section > .mainBanner > .mainBannerCont > .inner > ul > li:nth-child(2) { + background-image: url(../images/car2.png); + background-position: 50% 40%; + background-size: 50% cover; } + section > .mainBanner > .mainBannerCont > .inner > ul > li:nth-child(3) { + background-image: url(../images/dbnt.jpg); + background-position: 50% 0%; + background-repeat: no-repeat; + background-size: cover; } + section > .mainBanner > .mainBannerCont > .inner > ul > li:nth-child(3) > dl dt { + margin-top: -90px; + text-indent: -99999px; + width: 100%; + height: 390px; + background-image: url(../images/dbnt_text.png); + background-position: 50% 80%; + background-repeat: no-repeat; + background-size: cover; } + section > .mainBanner > .mainBannerCont > .inner > ul > li > dl { + margin-top: 0px; + color: #fff; + width: 100%; + padding: 10px 0; + background-color: rgba(0, 0, 0, 0.5); } + section > .mainBanner > .mainBannerCont > .inner > ul > li > dl > dt { + margin-bottom: 0px; + font-size: 40px; + font-weight: 600; } + section > .mainBanner > .mainBannerCont > .inner > ul > li > dl > dd { + line-height: 3.5em; + font-size: 20px; + font-weight: normal; } +section > .mainIndustries { + width: 1200px; + margin: 0 auto 60PX; } + section > .mainIndustries > p { + position: relative; + padding-top: 40px; + text-align: center; + font-size: 22px; + color: #000; } + section > .mainIndustries > p:after { + position: absolute; + bottom: -20px; + left: 50%; + margin-left: -50px; + width: 100px; + height: 3px; + background-color: #000; + content: ""; } + section > .mainIndustries ul { + padding-top: 40px; } + section > .mainIndustries ul > li { + overflow: hidden; + float: left; + width: 230px; + height: 230px; + margin-left: 125px; + border-radius: 300px; } + section > .mainIndustries ul > li > a { + display: block; + height: 230px; + transition: 0.3s; } + section > .mainIndustries ul > li > a > dl { + height: 100%; + transform: translateY(50%); + text-align: center; + color: #fff; } + section > .mainIndustries ul > li > a > dl > dt { + margin-top: -10px; + font-size: 30px; } + section > .mainIndustries ul > li > a > dl > dd { + margin-bottom: 20px; + line-height: 1.9em; + transition: 0.3s; } + section > .mainIndustries ul > li > a > dl > dd:nth-child(2) { + position: absolute; + top: -170px; + width: 100%; + height: 350px; + background-position: 50% 50%; + z-index: 0; } + section > .mainIndustries ul > li:nth-child(1) { + background: url(../images/btn_main01.jpg); + background-position: 0% 0%; + background-repeat: no-repeat; + background-size: cover; } + section > .mainIndustries ul > li:nth-child(2) { + background: url(../images/asd_01.jpg); + background-position: 10% 100%; + background-repeat: no-repeat; + background-size: cover; } + section > .mainIndustries ul > li:nth-child(3) { + background: url(../images/tt.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } +section > .mainOverView { + margin-top: 100px; + padding: 60px 0; + background-color: #efefef; } + section > .mainOverView > .inner { + width: 1200px; + margin: 0 auto; } + section > .mainOverView > .inner > ul > li { + float: left; } + section > .mainOverView > .inner > ul > li:nth-child(2) { + position: relative; + float: right; + margin-top: 90px; + margin-right: 80px; + background-color: lightblue; + width: 300px; + text-align: center; } + section > .mainOverView > .inner > ul > li:nth-child(2):after { + position: absolute; + top: -100px; + left: -100px; + width: 100px; + height: 100px; + content: ''; + background: url(../images/dot_l.PNG); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 100%; } + section > .mainOverView > .inner > ul > li:nth-child(2):before { + position: absolute; + top: -100px; + left: 300px; + width: 100px; + height: 100px; + content: ''; + background: url(../images/dot_r.PNG); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 100%; } + section > .mainOverView > .inner > ul > li:nth-child(2) > a { + display: block; + font-size: 16px; + padding: 15px 50px; + background-color: #0061a9; + color: #fff; } + section > .mainOverView > .inner > ul > li > dl > dt { + position: relative; + margin-bottom: 50px; + font-size: 25px; } + section > .mainOverView > .inner > ul > li > dl > dt::after { + position: absolute; + top: 40px; + left: 0; + width: 400px; + border: 1px solid #0061a9; + content: ''; } + section > .mainOverView > .inner > ul > li > dl > dd { + line-height: 1.5em; + font-size: 35px; } + section > .mainOverView > .inner > ul > li > dl > dd:nth-child(3) { + font-size: 15px; + color: #666666; } +section .mainRND { + position: relative; + margin-bottom: 0px; + width: 100%; + height: 190px; + background: url(../images/www.jpg); + background-attachment: fixed; + background-size: cover; + background-position: 50% 50%; + background-repeat: no-repeat; + z-index: 0; } + section .mainRND > h2:after { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 190px; + background-color: #707070; + opacity: 0.4; + content: ''; + z-index: -1; } + section .mainRND > ul { + width: 1200px; + margin: 50px auto 0; + text-align: center; + color: #fff; + z-index: 10 !important; } + section .mainRND > ul > li { + font-size: 30px; + z-index: 10; } + section .mainRND > ul > li:last-child { + margin-top: 20px; } + section .mainRND > ul > li:last-child > a { + padding: 10px 60px; + background-color: #777; + font-size: 15px; + color: #fff; + z-index: 9999; + transition: 0.3s; } + section .mainRND > ul > li:last-child > a:hover { + background-color: #0061a9; } + +/* +******************************************** +**************index.html의 css************** +******************************************** +*/ +/*서브 페이지 레이아웃*/ +.subBanner { + width: 100%; + height: 200px; + background: url(../images/company_b.jpg); + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; } + .subBanner > .inner { + width: 1200px; + margin: 0 auto; } + .subBanner > .inner > .subBannerInfo > ul { + margin-top: 90px; + float: right; + text-align: right; + width: 600px; } + .subBanner > .inner > .subBannerInfo > ul > li { + color: #fff; + line-height: 1.9em; + cursor: default; } + .subBanner > .inner > .subBannerInfo > ul > li:nth-child(1) { + font-size: 28px; } + .subBanner > .inner > .subBannerInfo > ul > li:nth-child(2) { + position: relative; + font-size: 15px; } + .subBanner > .inner > .subBannerInfo > ul > li:nth-child(2):after { + position: absolute; + top: -10px; + right: 0; + width: 200px; + border: 1px solid #fff; + content: ""; } + +.siteIndex { + padding: 7.5px 0; + border-bottom: 1px solid #dddddd; } + .siteIndex > .inner { + width: 1200px; + margin: 0 auto; } + +.sitemapContainer { + width: 1200px; + margin: 0 auto; } + .sitemapContainer > ul { + width: 100%; + margin-top: 100px; } + .sitemapContainer > ul > li { + float: left; } + .sitemapContainer > ul > li:nth-child(1) { + width: 300px; } + .sitemapContainer > ul > li:nth-child(1) > dl { + text-align: right; } + .sitemapContainer > ul > li:nth-child(1) > dl > dt { + font-size: 50px; + color: #0061a9; } + .sitemapContainer > ul > li:nth-child(1) > dl > dd { + font-size: 25px; + color: #666; } + .sitemapContainer > ul > li:nth-child(2) { + margin-bottom: 90px; + width: 900px; } + .sitemapContainer > ul > li:nth-child(2) > dl { + position: relative; + float: left; + padding-left: 90px; + width: 300px; + height: 150px; + padding-bottom: 80px; } + .sitemapContainer > ul > li:nth-child(2) > dl:after { + position: absolute; + bottom: 40px; + left: 90px; + content: ""; + width: 300px; + height: 4px; + background-color: #ddd; } + .sitemapContainer > ul > li:nth-child(2) > dl:nth-child(1) > dt:after { + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content: "Company"; } + .sitemapContainer > ul > li:nth-child(2) > dl:nth-child(2) > dt:after { + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content: "Business"; } + .sitemapContainer > ul > li:nth-child(2) > dl:nth-child(3) > dt:after { + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content: "Reference"; } + .sitemapContainer > ul > li:nth-child(2) > dl:nth-child(4) > dt:after { + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content: "Contact Us"; } + .sitemapContainer > ul > li:nth-child(2) > dl dt { + position: relative; + margin-bottom: 20px; + font-size: 25px; + font-weight: 600; + color: #000; } + .sitemapContainer > ul > li:nth-child(2) > dl dt:after { + font-weight: 500; } + .sitemapContainer > ul > li:nth-child(2) > dl dt:before { + position: absolute; + top: 30px; + left: 0px; + width: 300px; + height: 3px; + background-color: #0061a9; + font-size: 50px; + content: ""; } + .sitemapContainer > ul > li:nth-child(2) > dl dd { + position: relative; + margin-left: 35px; + line-height: 2em; } + .sitemapContainer > ul > li:nth-child(2) > dl dd > a { + color: #000; } + +@media screen and (max-width: 768px) { + section > .mainBanner { + width: 100%; + height: 280px; + background: url(../images/mvisual_02.jpg); + background-position: 50% 15%; + background-size: cover; + background-repeat: no-repeat; } + section > .mainBanner > .mainBannerCont { + width: 100%; } + section > .mainBanner > .mainBannerCont > .inner { + width: 100%; + margin: 0; } + section > .mainBanner > .mainBannerCont > .inner > ul { + margin-top: 0px; } + section > .mainBanner > .mainBannerCont > .inner > ul > li { + float: inherit; + height: 100%; + width: 100%; + text-align: center; } + section > .mainBanner > .mainBannerCont > .inner > ul > li:nth-child(3) > dl dt { + margin-top: -40px; + text-indent: -99999px; + width: 100%; + height: 160px; + background-image: url(../images/dbnt_m.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: 80%; } + section > .mainBanner > .mainBannerCont > .inner > ul > li > dl { + margin-top: -50px; + color: #fff; + width: 100%; + padding: 10px 0px; + background-color: rgba(0, 0, 0, 0.5); } + section > .mainBanner > .mainBannerCont > .inner > ul > li > dl > dt { + margin-bottom: 10px; + font-size: 23px; + font-weight: 600; } + section > .mainBanner > .mainBannerCont > .inner > ul > li > dl > dd { + line-height: 1.7em; + font-size: 13px; + font-weight: normal; + padding: 0 10px; } + section > .mainIndustries { + width: 100%; + margin: 0 auto 0PX; } + section > .mainIndustries > p { + position: relative; + padding-top: 80px; + text-align: center; + font-size: 18px; + color: #000; } + section > .mainIndustries > p:after { + position: absolute; + bottom: -20px; + left: 50%; + margin-left: -50px; + width: 100px; + height: 3px; + background-color: #000; + content: ""; } + section > .mainIndustries ul { + padding-top: 80px; } + section > .mainIndustries ul > li { + overflow: hidden; + float: inherit; + width: 100%; + height: 200px; + margin-left: 0px; + border-radius: 0px; } + section > .mainIndustries ul > li > a { + display: block; + height: 200px; + transition: 0.3s; } + section > .mainIndustries ul > li > a > dl { + height: 100%; + transform: translateY(50%); + text-align: center; + color: #fff; } + section > .mainIndustries ul > li > a > dl > dt { + margin-top: -10px; + font-size: 20px; } + section > .mainIndustries ul > li > a > dl > dd { + margin-bottom: 20px; + line-height: 1.9em; + transition: 0.3s; } + section > .mainIndustries ul > li > a > dl > dd:nth-child(2) { + position: absolute; + top: -170px; + width: 100%; + height: 350px; + background-position: 50% 50%; + z-index: 0; } + section > .mainIndustries ul > li:nth-child(1) { + background: url(../images/btn_main01.jpg); + background-position: 0% 0%; + background-repeat: no-repeat; + background-size: cover; } + section > .mainIndustries ul > li:nth-child(2) { + background: url(../images/asd_01.jpg); + background-position: 10% 100%; + background-repeat: no-repeat; + background-size: cover; } + section > .mainIndustries ul > li:nth-child(3) { + background: url(../images/tt.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + section > .mainOverView { + margin-top: 100px; + padding: 60px 0; + background-color: #efefef; } + section > .mainOverView > .inner { + width: 1200px; + margin: 0 auto; } + section > .mainOverView > .inner > ul > li { + float: left; } + section > .mainOverView > .inner > ul > li:nth-child(2) { + position: relative; + float: right; + margin-top: 90px; + margin-right: 80px; + background-color: lightblue; + width: 300px; + text-align: center; } + section > .mainOverView > .inner > ul > li:nth-child(2):after { + position: absolute; + top: -100px; + left: -100px; + width: 100px; + height: 100px; + content: ''; + background: url(../images/dot_l.PNG); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 100%; } + section > .mainOverView > .inner > ul > li:nth-child(2):before { + position: absolute; + top: -100px; + left: 300px; + width: 100px; + height: 100px; + content: ''; + background: url(../images/dot_r.PNG); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 100%; } + section > .mainOverView > .inner > ul > li:nth-child(2) > a { + display: block; + font-size: 16px; + padding: 15px 50px; + background-color: #0061a9; + color: #fff; } + section > .mainOverView > .inner > ul > li > dl > dt { + position: relative; + margin-bottom: 50px; + font-size: 25px; } + section > .mainOverView > .inner > ul > li > dl > dt::after { + position: absolute; + top: 40px; + left: 0; + width: 400px; + border: 1px solid #0061a9; + content: ''; } + section > .mainOverView > .inner > ul > li > dl > dd { + line-height: 1.5em; + font-size: 35px; } + section > .mainOverView > .inner > ul > li > dl > dd:nth-child(3) { + font-size: 15px; + color: #666666; } + section .mainRND { + position: relative; + margin-bottom: 0px; + width: 100%; + height: 200px; + background: url(../images/www.jpg); + background-attachment: fixed; + background-size: cover; + background-position: 50% 50%; + background-repeat: no-repeat; + z-index: 0; } + section .mainRND > h2:after { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 200px; + background-color: #707070; + opacity: 0.4; + content: ''; + z-index: -1; } + section .mainRND > ul { + width: 100%; + margin: 60px auto 0; + text-align: center; + color: #fff; + z-index: 10 !important; } + section .mainRND > ul > li { + font-size: 20px; + z-index: 10; } + section .mainRND > ul > li:last-child { + margin-top: 20px; } + section .mainRND > ul > li:last-child > a { + padding: 10px 60px; + background-color: #777; + font-size: 15px; + color: #fff; + z-index: 9999; + transition: 0.3s; } + section .mainRND > ul > li:last-child > a:hover { + background-color: #0061a9; } + + .subBanner { + width: 100%; + height: 250px; + background: url(../images/company.jpg); + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; } + .subBanner > .inner { + width: 100%; + margin: 0; } + .subBanner > .inner > .subBannerInfo > ul { + margin-top: 60px; + float: inherit; + text-align: center; + width: 100%; } + .subBanner > .inner > .subBannerInfo > ul > li { + color: #fff; + line-height: 1.9em; + cursor: default; } + .subBanner > .inner > .subBannerInfo > ul > li:nth-child(1) { + font-size: 30px; } + .subBanner > .inner > .subBannerInfo > ul > li:nth-child(2) { + position: relative; + font-size: 15px; + padding: 0 90px; } + .subBanner > .inner > .subBannerInfo > ul > li:nth-child(2):after { + position: absolute; + top: -10px; + right: 50%; + transform: translateX(50%); + width: 200px; + border: 1px solid #fff; + content: ""; } + + .siteIndex { + padding: 7.5px 0; + text-align: center; + border-bottom: 1px solid #dddddd; + font-size: 13px; } + .siteIndex > .inner { + width: 100%; + margin: 0; } + + .sitemapContainer { + width: 100%; + margin: 0; } + .sitemapContainer > ul { + width: 100%; + margin-top: 100px; } + .sitemapContainer > ul > li { + float: inherit; } + .sitemapContainer > ul > li:nth-child(1) { + width: 100%; + margin: 100px 0; } + .sitemapContainer > ul > li:nth-child(1) > dl { + text-align: center; } + .sitemapContainer > ul > li:nth-child(1) > dl > dt { + font-size: 50px; + color: #0061a9; } + .sitemapContainer > ul > li:nth-child(1) > dl > dd { + font-size: 25px; + color: #666; } + .sitemapContainer > ul > li:nth-child(2) { + margin-top: 50px; + margin-bottom: 90px; + width: 100%; } + .sitemapContainer > ul > li:nth-child(2) > dl { + position: relative; + float: left; + padding-left: 0px; + width: 100%; + height: 150px; + padding-bottom: 80px; } + .sitemapContainer > ul > li:nth-child(2) > dl:after { + position: absolute; + bottom: 40px; + left: 0px; + content: ""; + width: 100%; + height: 4px; + background-color: #ddd; } + .sitemapContainer > ul > li:nth-child(2) > dl:nth-child(1) > dt:after { + display: none; + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content: "Company"; } + .sitemapContainer > ul > li:nth-child(2) > dl:nth-child(2) > dt:after { + display: none; + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content: "Business"; } + .sitemapContainer > ul > li:nth-child(2) > dl:nth-child(3) > dt:after { + display: none; + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content: "Research and Development"; } + .sitemapContainer > ul > li:nth-child(2) > dl:nth-child(4) > dt:after { + display: none; + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content: "Contact Us"; } + .sitemapContainer > ul > li:nth-child(2) > dl dt { + position: relative; + text-align: center; + margin-bottom: 20px; + font-size: 25px; + font-weight: 600; + color: #000; } + .sitemapContainer > ul > li:nth-child(2) > dl dt:after { + font-weight: 500; } + .sitemapContainer > ul > li:nth-child(2) > dl dt:before { + position: absolute; + top: 30px; + left: 0px; + width: 100%; + height: 3px; + background-color: #0061a9; + font-size: 50px; + content: ""; } + .sitemapContainer > ul > li:nth-child(2) > dl dd { + position: relative; + margin-left: 0px; + text-align: center; + line-height: 2em; + border-bottom: 1px solid #ddd; } + .sitemapContainer > ul > li:nth-child(2) > dl dd > a { + color: #000; } } + +/*# sourceMappingURL=style.css.map */ diff --git a/css/style.css.map b/css/style.css.map new file mode 100644 index 0000000..35f6a41 --- /dev/null +++ b/css/style.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": ";AAGA,SAAU;EACN,KAAK,EAAG,CAAC;;AAGb,eAAgB;EACZ,KAAK,EAAE,IAAI;EACX,OAAO,EAAE,KAAK;EACd,OAAO,EAAE,EAAE;;AAGf,OAAQ;EACJ,WAAW,EAAE,QAAQ;EACrB,KAAK,EAAE,CAAC;EACR,MAAM,EAAE,CAAC;;AAGb,KAAM;EACF,KAAK,EAAE,IAAI;;AAKf,SAAS;AAYL,qBAAa;EACT,QAAQ,EAAE,MAAM;EAChB,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,KAAK;EAGb,mBAAmB,EAAE,OAAO;EAC5B,eAAe,EAAE,KAAK;EACtB,iBAAiB,EAAE,SAAS;EAE5B,uCAAiB;IACb,KAAK,EAAE,IAAI;IAEX,gDAAQ;MACJ,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,KAAK;MAGT,0DAAG;QACC,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,KAAK,EAAC,IAAI;QACV,MAAM,EAAE,KAAK;QACT,KAAK,EAAC,IAAI;QACV,UAAU,EAAE,MAAM;QAElB,uEAAe;UACX,gBAAgB,EAAE,4BAA4B;UAC9C,mBAAmB,EAAE,MAAM;QAI/B,uEAAe;UACX,gBAAgB,EAAE,uBAAuB;UACzC,mBAAmB,EAAE,OAAO;UAC5B,eAAe,EAAE,SAAS;QAK9B,uEAAe;UACX,gBAAgB,EAAE,uBAAuB;UACzC,mBAAmB,EAAE,MAAM;UAC3B,iBAAiB,EAAE,SAAS;UAC5B,eAAe,EAAE,KAAK;UAGlB,+EAAG;YACC,UAAU,EAAE,KAAK;YACjB,WAAW,EAAE,QAAQ;YACrB,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,KAAK;YACb,gBAAgB,EAAE,4BAA4B;YAC9C,mBAAmB,EAAE,OAAO;YAC5B,iBAAiB,EAAE,SAAS;YAC5B,eAAe,EAAE,KAAK;QAMlC,+DAAI;UACA,UAAU,EAAE,GAAG;UACf,KAAK,EAAE,IAAI;UACX,KAAK,EAAE,IAAI;UACX,OAAO,EAAE,MAAM;UACf,gBAAgB,EAAE,kBAAqB;UAEvC,oEAAI;YACA,aAAa,EAAE,GAAG;YAClB,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,GAAG;UAKpB,oEAAI;YACA,WAAW,EAAE,KAAK;YAClB,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,MAAM;AAanD,yBAAiB;EACb,KAAK,EAAE,MAAM;EACb,MAAM,EAAE,WAAW;EAEnB,6BAAG;IACC,QAAQ,EAAE,QAAQ;IAClB,WAAW,EAAG,IAAI;IAClB,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,IAAI;IACf,KAAK,EAAE,IAAI;IAEX,mCAAQ;MACJ,QAAQ,EAAE,QAAQ;MAClB,MAAM,EAAE,KAAK;MACb,IAAI,EAAE,GAAG;MACT,WAAW,EAAG,KAAK;MACnB,KAAK,EAAE,KAAK;MACZ,MAAM,EAAE,GAAG;MACX,gBAAgB,EAAE,IAAI;MACtB,OAAO,EAAE,EAAE;EAKnB,4BAAG;IACC,WAAW,EAAE,IAAI;IAEjB,iCAAI;MACA,QAAQ,EAAE,MAAM;MAChB,KAAK,EAAE,IAAI;MACX,KAAK,EAAE,KAAK;MACZ,MAAM,EAAE,KAAK;MACb,WAAW,EAAE,KAAK;MAClB,aAAa,EAAE,KAAK;MAGpB,qCAAG;QACC,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,KAAK;QACb,UAAU,EAAE,IAAI;QAIhB,0CAAI;UACA,MAAM,EAAE,IAAI;UACZ,SAAS,EAAE,eAAe;UAC1B,UAAU,EAAE,MAAM;UAClB,KAAK,EAAE,IAAI;UAGX,+CAAI;YACA,UAAU,EAAE,KAAK;YACjB,SAAS,EAAE,IAAI;UAInB,+CAAI;YACA,aAAa,EAAE,IAAI;YACnB,WAAW,EAAE,KAAK;YAClB,UAAU,EAAE,IAAI;YAGhB,4DAAe;cACX,QAAQ,EAAE,QAAQ;cAClB,GAAG,EAAE,MAAM;cACX,KAAK,EAAE,IAAI;cACX,MAAM,EAAE,KAAK;cACb,mBAAmB,EAAE,OAAO;cAC5B,OAAO,EAAE,CAAC;MAW1B,8CAAe;QACX,UAAU,EAAE,6BAA6B;QACzC,mBAAmB,EAAE,KAAK;QAC1B,iBAAiB,EAAE,SAAS;QAC5B,eAAe,EAAE,KAAK;MAY1B,8CAAe;QACX,UAAU,EAAE,yBAAyB;QACrC,mBAAmB,EAAE,QAAQ;QAC7B,iBAAiB,EAAE,SAAS;QAC5B,eAAe,EAAE,KAAK;MAU1B,8CAAe;QACX,UAAU,EAAE,qBAAqB;QACjC,mBAAmB,EAAE,OAAO;QAC5B,iBAAiB,EAAE,SAAS;QAC5B,eAAe,EAAE,KAAK;AAmBtC,uBAAe;EACX,UAAU,EAAG,KAAK;EAClB,OAAO,EAAG,MAAM;EAChB,gBAAgB,EAAE,OAAO;EAEzB,gCAAQ;IA7OZ,KAAK,EA8OqB,MAAM;IA7OhC,MAAM,EA6O2B,MAAO;IAI5B,0CAAI;MACA,KAAK,EAAC,IAAI;MAEV,uDAAe;QACX,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,KAAK;QACZ,UAAU,EAAG,IAAI;QACjB,YAAY,EAAG,IAAI;QACnB,gBAAgB,EAAE,SAAS;QAC3B,KAAK,EAAE,KAAK;QACZ,UAAU,EAAE,MAAM;QAElB,6DAAQ;UACJ,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,MAAM;UACX,IAAI,EAAE,MAAM;UACZ,KAAK,EAAE,KAAK;UACZ,MAAM,EAAE,KAAK;UACb,OAAO,EAAG,EAAE;UACZ,UAAU,EAAE,wBAAwB;UACpC,iBAAiB,EAAE,SAAS;UAC5B,mBAAmB,EAAE,OAAO;UAC5B,eAAe,EAAE,IAAI;QAGzB,8DAAS;UACL,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,MAAM;UACX,IAAI,EAAE,KAAK;UACX,KAAK,EAAE,KAAK;UACZ,MAAM,EAAE,KAAK;UACb,OAAO,EAAG,EAAE;UACZ,UAAU,EAAE,wBAAwB;UACpC,iBAAiB,EAAE,SAAS;UAC5B,mBAAmB,EAAE,OAAO;UAC5B,eAAe,EAAE,IAAI;QAGzB,2DAAG;UACC,OAAO,EAAE,KAAK;UACd,SAAS,EAAE,IAAI;UACf,OAAO,EAAE,SAAS;UAClB,gBAAgB,EA3ThC,OAAO;UA4TS,KAAK,EAAE,IAAI;MAOf,oDAAI;QACA,QAAQ,EAAE,QAAQ;QAClB,aAAa,EAAE,IAAI;QACnB,SAAS,EAAE,IAAI;QAEf,2DAAS;UACL,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,IAAI;UACT,IAAI,EAAE,CAAC;UACP,KAAK,EAAE,KAAK;UACZ,MAAM,EAAE,iBAAoB;UAC5B,OAAO,EAAE,EAAE;MAInB,oDAAI;QACA,WAAW,EAAE,KAAK;QAClB,SAAS,EAAE,IAAI;QAEf,iEAAe;UACX,SAAS,EAAE,IAAI;UACf,KAAK,EAAE,OAAO;AAW1C,gBAAS;EACL,QAAQ,EAAE,QAAQ;EAClB,aAAa,EAAE,GAAG;EAClB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,KAAK;EACb,UAAU,EAAE,sBAAsB;EAClC,qBAAqB,EAAE,KAAK;EAC5B,eAAe,EAAE,KAAK;EACtB,mBAAmB,EAAE,OAAO;EAC5B,iBAAiB,EAAE,SAAS;EAC5B,OAAO,EAAE,CAAC;EAKN,2BAAQ;IAEJ,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,CAAC;IACN,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,KAAK;IACb,gBAAgB,EAxXlB,OAAO;IAyXL,OAAO,EAAE,GAAG;IACZ,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;EAInB,qBAAI;IACA,KAAK,EAAE,MAAM;IACb,MAAM,EAAE,WAAW;IACnB,UAAU,EAAE,MAAM;IAClB,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,aAAa;IAGtB,0BAAI;MACA,SAAS,EAAE,IAAI;MACf,OAAO,EAAE,EAAE;MAEX,qCAAa;QACT,UAAU,EAAE,IAAI;QAEhB,yCAAG;UACC,OAAO,EAAE,SAAS;UAClB,gBAAgB,EAAE,IAAI;UACtB,SAAS,EAAE,IAAI;UACf,KAAK,EAAE,IAAI;UACX,OAAO,EAAE,IAAI;UACb,UAAU,EAAE,IAAI;UAEhB,+CAAQ;YACJ,gBAAgB,EAxZhC,OAAO;;AAwanB;;;;EAIE;AAGF,eAAe;AAEf,UAAW;EACP,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,KAAK;EACb,UAAU,EAAE,4BAA4B;EACxC,iBAAiB,EAAE,SAAS;EAC5B,eAAe,EAAE,KAAK;EACtB,mBAAmB,EAAE,OAAO;EAE5B,mBAAQ;IA1ZR,KAAK,EA2ZiB,MAAM;IA1Z5B,MAAM,EA0ZuB,MAAO;IAK5B,yCAAI;MACA,UAAU,EAAG,IAAI;MACjB,KAAK,EAAC,KAAK;MACX,UAAU,EAAE,KAAK;MACjB,KAAK,EAAE,KAAK;MAEZ,8CAAI;QACA,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,KAAK;QAClB,MAAM,EAAE,OAAO;QAEf,2DAAe;UACX,SAAS,EAAE,IAAI;QAGnB,2DAAe;UACX,QAAQ,EAAE,QAAQ;UAClB,SAAS,EAAE,IAAI;UAEf,iEAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,KAAK;YACV,KAAK,EAAG,CAAC;YACT,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,cAAc;YACtB,OAAO,EAAG,EAAE;;AAaxC,UAAW;EACP,OAAO,EAAE,OAAO;EAChB,aAAa,EAAE,iBAAiB;EAEhC,mBAAQ;IA1cR,KAAK,EA2ciB,MAAM;IA1c5B,MAAM,EA0cuB,MAAO;;AAKxC,iBAAkB;EAhdd,KAAK,EAkda,MAAM;EAjdxB,MAAM,EAidmB,MAAO;EAEhC,sBAAI;IACA,KAAK,EAAE,IAAI;IACX,UAAU,EAAE,KAAK;IAEjB,2BAAI;MACA,KAAK,EAAC,IAAI;MAEV,wCAAe;QACX,KAAK,EAAE,KAAK;QAEZ,6CAAG;UACC,UAAU,EAAE,KAAK;UAEjB,kDAAI;YACA,SAAS,EAAE,IAAI;YACf,KAAK,EAlgBjB,OAAO;UAogBC,kDAAI;YACA,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;MAMvB,wCAAe;QACX,aAAa,EAAE,IAAI;QACnB,KAAK,EAAE,KAAK;QAEZ,6CAAI;UACA,QAAQ,EAAE,QAAQ;UAClB,KAAK,EAAE,IAAI;UACX,YAAY,EAAE,IAAI;UAClB,KAAK,EAAE,KAAK;UACZ,MAAM,EAAE,KAAK;UACb,cAAc,EAAE,IAAI;UAEpB,mDAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,MAAM,EAAE,IAAI;YACZ,IAAI,EAAE,IAAI;YACV,OAAO,EAAC,EAAE;YACV,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,GAAG;YACX,gBAAgB,EAAE,IAAI;UAUlB,qEAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,IAAI;YACT,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,OAAO,EAAC,SAAS;UAarB,qEAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,IAAI;YACT,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,OAAO,EAAC,UAAU;UAWtB,qEAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,IAAI;YACT,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,OAAO,EAAC,WAAW;UAUvB,qEAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,IAAI;YACT,IAAI,EAAE,KAAK;YACX,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,OAAO,EAAC,YAAY;UAMhC,gDAAG;YACC,QAAQ,EAAE,QAAQ;YAClB,aAAa,EAAE,IAAI;YACnB,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,GAAG;YAChB,KAAK,EAAE,IAAI;YAEX,sDAAQ;cACJ,WAAW,EAAE,GAAG;YAEpB,uDAAS;cACL,QAAQ,EAAE,QAAQ;cAClB,GAAG,EAAE,IAAI;cACT,IAAI,EAAE,GAAG;cACT,KAAK,EAAE,KAAK;cACZ,MAAM,EAAE,GAAG;cACX,gBAAgB,EAznBhC,OAAO;cA0nBS,SAAS,EAAE,IAAI;cACf,OAAO,EAAC,EAAE;UAMlB,gDAAG;YACC,QAAQ,EAAE,QAAQ;YAClB,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,GAAG;YAGhB,oDAAG;cACC,KAAK,EAAE,IAAI;;AAiBvC,oCAAoC;EAI5B,qBAAa;IACT,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,KAAK;IACb,UAAU,EAAE,6BAA6B;IACzC,mBAAmB,EAAE,OAAO;IAC5B,eAAe,EAAE,KAAK;IACtB,iBAAiB,EAAE,SAAS;IAE5B,uCAAiB;MACb,KAAK,EAAE,IAAI;MAEX,gDAAQ;QAzoBpB,KAAK,EA0oB6B,IAAI;QAzoBtC,MAAM,EAyoBkC,CAAC;QAEzB,qDAAI;UACA,UAAU,EAAG,GAAG;UAEhB,0DAAG;YACC,KAAK,EAAE,OAAO;YACd,MAAM,EAAE,IAAI;YACZ,KAAK,EAAE,IAAI;YACX,UAAU,EAAE,MAAM;YAIV,+EAAG;cACC,UAAU,EAAE,KAAK;cACjB,WAAW,EAAE,QAAQ;cACrB,KAAK,EAAE,IAAI;cACX,MAAM,EAAE,KAAK;cACb,gBAAgB,EAAE,yBAAyB;cAC3C,mBAAmB,EAAE,OAAO;cAC5B,iBAAiB,EAAE,SAAS;cAC5B,eAAe,EAAE,GAAG;YAKhC,+DAAI;cACJ,UAAU,EAAE,KAAK;cACjB,KAAK,EAAE,IAAI;cACX,KAAK,EAAE,IAAI;cACX,OAAO,EAAE,QAAQ;cACjB,gBAAgB,EAAE,kBAAqB;cAGvC,oEAAI;gBACA,aAAa,EAAE,IAAI;gBACnB,SAAS,EAAE,IAAI;gBACf,WAAW,EAAE,GAAG;cAIpB,oEAAI;gBACA,WAAW,EAAE,KAAK;gBAClB,SAAS,EAAE,IAAI;gBACf,WAAW,EAAE,MAAM;gBACnB,OAAO,EAAE,MAAM;EAcvC,yBAAiB;IACb,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,UAAU;IAElB,6BAAG;MACC,QAAQ,EAAE,QAAQ;MAClB,WAAW,EAAG,IAAI;MAClB,UAAU,EAAE,MAAM;MAClB,SAAS,EAAE,IAAI;MACf,KAAK,EAAE,IAAI;MAEX,mCAAQ;QACJ,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,GAAG;QACT,WAAW,EAAG,KAAK;QACnB,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,GAAG;QACX,gBAAgB,EAAE,IAAI;QACtB,OAAO,EAAE,EAAE;IAKnB,4BAAG;MACC,WAAW,EAAE,IAAI;MAEjB,iCAAI;QACA,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,KAAK;QACb,WAAW,EAAE,GAAG;QAChB,aAAa,EAAE,GAAG;QAGlB,qCAAG;UACC,OAAO,EAAE,KAAK;UACd,MAAM,EAAE,KAAK;UACb,UAAU,EAAE,IAAI;UAIhB,0CAAI;YACA,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,eAAe;YAC1B,UAAU,EAAE,MAAM;YAClB,KAAK,EAAE,IAAI;YAGX,+CAAI;cACA,UAAU,EAAE,KAAK;cACjB,SAAS,EAAE,IAAI;YAInB,+CAAI;cACA,aAAa,EAAE,IAAI;cACnB,WAAW,EAAE,KAAK;cAClB,UAAU,EAAE,IAAI;cAGhB,4DAAe;gBACX,QAAQ,EAAE,QAAQ;gBAClB,GAAG,EAAE,MAAM;gBACX,KAAK,EAAE,IAAI;gBACX,MAAM,EAAE,KAAK;gBACb,mBAAmB,EAAE,OAAO;gBAC5B,OAAO,EAAE,CAAC;QAW1B,8CAAe;UACX,UAAU,EAAE,6BAA6B;UACzC,mBAAmB,EAAE,KAAK;UAC1B,iBAAiB,EAAE,SAAS;UAC5B,eAAe,EAAE,KAAK;QAY1B,8CAAe;UACX,UAAU,EAAE,yBAAyB;UACrC,mBAAmB,EAAE,QAAQ;UAC7B,iBAAiB,EAAE,SAAS;UAC5B,eAAe,EAAE,KAAK;QAU1B,8CAAe;UACX,UAAU,EAAE,qBAAqB;UACjC,mBAAmB,EAAE,OAAO;UAC5B,iBAAiB,EAAE,SAAS;UAC5B,eAAe,EAAE,KAAK;EAmBtC,uBAAe;IACX,UAAU,EAAG,KAAK;IAClB,OAAO,EAAG,MAAM;IAChB,gBAAgB,EAAE,OAAO;IAEzB,gCAAQ;MA90BhB,KAAK,EA+0ByB,MAAM;MA90BpC,MAAM,EA80B+B,MAAO;MAI5B,0CAAI;QACA,KAAK,EAAC,IAAI;QAEV,uDAAe;UACX,QAAQ,EAAE,QAAQ;UAClB,KAAK,EAAE,KAAK;UACZ,UAAU,EAAG,IAAI;UACjB,YAAY,EAAG,IAAI;UACnB,gBAAgB,EAAE,SAAS;UAC3B,KAAK,EAAE,KAAK;UACZ,UAAU,EAAE,MAAM;UAElB,6DAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,MAAM;YACX,IAAI,EAAE,MAAM;YACZ,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,KAAK;YACb,OAAO,EAAG,EAAE;YACZ,UAAU,EAAE,wBAAwB;YACpC,iBAAiB,EAAE,SAAS;YAC5B,mBAAmB,EAAE,OAAO;YAC5B,eAAe,EAAE,IAAI;UAGzB,8DAAS;YACL,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,MAAM;YACX,IAAI,EAAE,KAAK;YACX,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,KAAK;YACb,OAAO,EAAG,EAAE;YACZ,UAAU,EAAE,wBAAwB;YACpC,iBAAiB,EAAE,SAAS;YAC5B,mBAAmB,EAAE,OAAO;YAC5B,eAAe,EAAE,IAAI;UAGzB,2DAAG;YACC,OAAO,EAAE,KAAK;YACd,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,SAAS;YAClB,gBAAgB,EA55BpC,OAAO;YA65Ba,KAAK,EAAE,IAAI;QAOf,oDAAI;UACA,QAAQ,EAAE,QAAQ;UAClB,aAAa,EAAE,IAAI;UACnB,SAAS,EAAE,IAAI;UAEf,2DAAS;YACL,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,IAAI;YACT,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,iBAAoB;YAC5B,OAAO,EAAE,EAAE;QAInB,oDAAI;UACA,WAAW,EAAE,KAAK;UAClB,SAAS,EAAE,IAAI;UAEf,iEAAe;YACX,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,OAAO;EAW1C,gBAAS;IACL,QAAQ,EAAE,QAAQ;IAClB,aAAa,EAAE,GAAG;IAClB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,KAAK;IACb,UAAU,EAAE,sBAAsB;IAClC,qBAAqB,EAAE,KAAK;IAC5B,eAAe,EAAE,KAAK;IACtB,mBAAmB,EAAE,OAAO;IAC5B,iBAAiB,EAAE,SAAS;IAC5B,OAAO,EAAE,CAAC;IAKN,2BAAQ;MAEJ,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,CAAC;MACN,IAAI,EAAE,CAAC;MACP,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,KAAK;MACb,gBAAgB,EAz9BtB,OAAO;MA09BD,OAAO,EAAE,GAAG;MACZ,OAAO,EAAE,EAAE;MACX,OAAO,EAAE,EAAE;IAInB,qBAAI;MACA,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,WAAW;MACnB,UAAU,EAAE,MAAM;MAClB,KAAK,EAAE,IAAI;MACX,OAAO,EAAE,aAAa;MAGtB,0BAAI;QACA,SAAS,EAAE,IAAI;QACf,OAAO,EAAE,EAAE;QAEX,qCAAa;UACT,UAAU,EAAE,IAAI;UAEhB,yCAAG;YACC,OAAO,EAAE,SAAS;YAClB,gBAAgB,EAAE,IAAI;YACtB,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;YACX,OAAO,EAAE,IAAI;YACb,UAAU,EAAE,IAAI;YAEhB,+CAAQ;cACJ,gBAAgB,EAz/BpC,OAAO;;EAygCf,UAAW;IACP,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,KAAK;IACb,UAAU,EAAE,0BAA0B;IACtC,iBAAiB,EAAE,SAAS;IAC5B,eAAe,EAAE,KAAK;IACtB,mBAAmB,EAAE,OAAO;IAE5B,mBAAQ;MAl/BZ,KAAK,EAm/BqB,IAAI;MAl/B9B,MAAM,EAk/B0B,CAAC;MAKrB,yCAAI;QACA,UAAU,EAAG,IAAI;QACjB,KAAK,EAAE,OAAO;QACd,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,IAAI;QAEX,8CAAI;UACA,KAAK,EAAE,IAAI;UACX,WAAW,EAAE,KAAK;UAClB,MAAM,EAAE,OAAO;UAEf,2DAAe;YACX,SAAS,EAAE,IAAI;UAGnB,2DAAe;YACX,QAAQ,EAAE,QAAQ;YAClB,SAAS,EAAE,IAAI;YACf,OAAO,EAAE,MAAM;YAEf,iEAAQ;cACJ,QAAQ,EAAE,QAAQ;cAClB,GAAG,EAAE,KAAK;cACV,KAAK,EAAG,GAAG;cACX,SAAS,EAAE,eAAe;cAC1B,KAAK,EAAE,KAAK;cACZ,MAAM,EAAE,cAAc;cACtB,OAAO,EAAG,EAAE;;EAaxC,UAAW;IACP,OAAO,EAAE,OAAO;IAChB,UAAU,EAAE,MAAM;IAClB,aAAa,EAAE,iBAAiB;IAChC,SAAS,EAAE,IAAI;IAEf,mBAAQ;MAtiCZ,KAAK,EAuiCqB,IAAI;MAtiC9B,MAAM,EAsiC0B,CAAC;;EAMjC,iBAAkB;IA7iClB,KAAK,EA+iCiB,IAAI;IA9iC1B,MAAM,EA8iCsB,CAAC;IAEzB,sBAAI;MACA,KAAK,EAAE,IAAI;MACX,UAAU,EAAE,KAAK;MAEjB,2BAAI;QACA,KAAK,EAAE,OAAO;QAEd,wCAAe;UACX,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,OAAO;UAEf,6CAAG;YACC,UAAU,EAAE,MAAM;YAElB,kDAAI;cACA,SAAS,EAAE,IAAI;cACf,KAAK,EAhmCrB,OAAO;YAkmCK,kDAAI;cACA,SAAS,EAAE,IAAI;cACf,KAAK,EAAE,IAAI;QAMvB,wCAAe;UACX,UAAU,EAAE,IAAI;UAChB,aAAa,EAAE,IAAI;UACnB,KAAK,EAAE,IAAI;UAEX,6CAAI;YACA,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,IAAI;YACX,YAAY,EAAE,GAAG;YACjB,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,KAAK;YACb,cAAc,EAAE,IAAI;YAEpB,mDAAQ;cACJ,QAAQ,EAAE,QAAQ;cAClB,MAAM,EAAE,IAAI;cACZ,IAAI,EAAE,GAAG;cACT,OAAO,EAAC,EAAE;cACV,KAAK,EAAE,IAAI;cACX,MAAM,EAAE,GAAG;cACX,gBAAgB,EAAE,IAAI;YAWlB,qEAAQ;cACJ,OAAO,EAAE,IAAI;cACb,QAAQ,EAAE,QAAQ;cAClB,GAAG,EAAE,IAAI;cACT,IAAI,EAAE,KAAK;cACX,SAAS,EAAE,IAAI;cACf,KAAK,EAAE,IAAI;cACX,OAAO,EAAC,SAAS;YAarB,qEAAQ;cACJ,OAAO,EAAE,IAAI;cACb,QAAQ,EAAE,QAAQ;cAClB,GAAG,EAAE,IAAI;cACT,IAAI,EAAE,KAAK;cACX,SAAS,EAAE,IAAI;cACf,KAAK,EAAE,IAAI;cACX,OAAO,EAAC,UAAU;YAWtB,qEAAQ;cACJ,OAAO,EAAE,IAAI;cACb,QAAQ,EAAE,QAAQ;cAClB,GAAG,EAAE,IAAI;cACT,IAAI,EAAE,KAAK;cACX,SAAS,EAAE,IAAI;cACf,KAAK,EAAE,IAAI;cACX,OAAO,EAAC,0BAA0B;YAUtC,qEAAQ;cACJ,OAAO,EAAE,IAAI;cACb,QAAQ,EAAE,QAAQ;cAClB,GAAG,EAAE,IAAI;cACT,IAAI,EAAE,KAAK;cACX,SAAS,EAAE,IAAI;cACf,KAAK,EAAE,IAAI;cACX,OAAO,EAAC,YAAY;YAMhC,gDAAG;cACC,QAAQ,EAAE,QAAQ;cAClB,UAAU,EAAE,MAAM;cAClB,aAAa,EAAE,IAAI;cACnB,SAAS,EAAE,IAAI;cACf,WAAW,EAAE,GAAG;cAChB,KAAK,EAAE,IAAI;cAEX,sDAAQ;gBACJ,WAAW,EAAE,GAAG;cAEpB,uDAAS;gBACL,QAAQ,EAAE,QAAQ;gBAClB,GAAG,EAAE,IAAI;gBACT,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,IAAI;gBACX,MAAM,EAAE,GAAG;gBACX,gBAAgB,EA9tCpC,OAAO;gBA+tCa,SAAS,EAAE,IAAI;gBACf,OAAO,EAAC,EAAE;YAMlB,gDAAG;cACC,QAAQ,EAAE,QAAQ;cAClB,WAAW,EAAE,GAAG;cAChB,UAAU,EAAE,MAAM;cAClB,WAAW,EAAE,GAAG;cAChB,aAAa,EAAE,cAAc;cAG7B,oDAAG;gBACC,KAAK,EAAE,IAAI", +"sources": ["style.scss"], +"names": [], +"file": "style.css" +} \ No newline at end of file diff --git a/css/style.scss b/css/style.scss new file mode 100644 index 0000000..e8fc3e4 --- /dev/null +++ b/css/style.scss @@ -0,0 +1,1291 @@ +$mainColor :#0061a9; +$mainColor2 : #707070; + +.clearfix { + *zoom : 1; +} + +.clearfix:after { + clear: both; + display: block; + content: ""; +} + +.hidden { + text-indent: -99999px; + width: 0; + height: 0; +} + +#wrap { + width: 100%; +} + + + +/*기본 세팅*/ + + + + +@mixin innerSet ( $width, $margin){ + width : $width; + margin : $margin; +} + +section { + + >.mainBanner { + overflow: hidden; + position: relative; + width: 100%; + height: 300px; + //background: url(../images/mvisual_02.jpg); + //background: url(../images/banner_01.png); + background-position: 50% 80%; + background-size: cover; + background-repeat: no-repeat; + + >.mainBannerCont { + width: 100%; + + >.inner { + width: 100%; + height: 510px; + + >ul { + >li{ + position: absolute; + top: 0; + left: 0; + float:left; + height: 300px; + width:100%; + text-align: center; + + &:nth-child(1) { + background-image: url(../images/banner_01.png); + background-position: 50% 0%; + + } + + &:nth-child(2) { + background-image: url(../images/car2.png); + background-position: 50% 40%; + background-size: 50% cover; + + } + + + &:nth-child(3) { + background-image: url(../images/dbnt.jpg); + background-position: 50% 0%; + background-repeat: no-repeat; + background-size: cover; + + >dl { + dt { + margin-top: -90px; + text-indent: -99999px; + width: 100%; + height: 390px; + background-image: url(../images/dbnt_text.png); + background-position: 50% 80%; + background-repeat: no-repeat; + background-size: cover; + } + } + + } + + >dl { + margin-top: 0px; + color: #fff; + width: 100%; + padding: 10px 0; + background-color: rgba(000,000,000,0.5); + + >dt { + margin-bottom: 0px; + font-size: 40px; + font-weight: 600; + + + } + + >dd { + line-height: 3.5em; + font-size: 20px; + font-weight: normal; + + + } + + } + } + }//end of mainBanner > inner > ul + + }//end of mainBanner > inner + }//end of mainBannerCont + }//end of mainBanner + + >.mainIndustries { + width: 1200px; + margin: 0 auto 60PX; + + >p { + position: relative; + padding-top : 40px; + text-align: center; + font-size: 22px; + color: #000; + + &:after { + position: absolute; + bottom: -20px; + left: 50%; + margin-left : -50px; + width: 100px; + height: 3px; + background-color: #000; + content: ""; + } + + } + + ul { + padding-top: 40px; + + >li { + overflow: hidden; + float: left; + width: 230px; + height: 230px; + margin-left: 125px; + border-radius: 300px; + + + >a { + display: block; + height: 230px; + transition: 0.3s; + + + + >dl { + height: 100%; + transform: translateY(50%); + text-align: center; + color: #fff; + + + >dt { + margin-top: -10px; + font-size: 30px; + + } + + >dd { + margin-bottom: 20px; + line-height: 1.9em; + transition: 0.3s; + + + &:nth-child(2) { + position: absolute; + top: -170px; + width: 100%; + height: 350px; + background-position: 50% 50%; + z-index: 0; + + + } + + + } + } + + } + + &:nth-child(1) { + background: url(../images/btn_main01.jpg); + background-position: 0% 0%; + background-repeat: no-repeat; + background-size: cover; + + + + dd { + &:last-child { + + } + + } + } + + &:nth-child(2) { + background: url(../images/asd_01.jpg); + background-position: 10% 100%; + background-repeat: no-repeat; + background-size: cover; + + dd { + &:last-child { + + } + + } + } + + &:nth-child(3) { + background: url(../images/tt.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + + dd { + &:last-child { + + } + + } + } + + + + }//end of mainIndustries > ul > li + + }//end of mainIndustries > ul + + }//end of mainIndustries + + + >.mainOverView { + margin-top : 100px; + padding: 60px 0; + background-color: #efefef; + + >.inner { + @include innerSet(1200px,0 auto ); + + >ul { + + >li { + float:left; + + &:nth-child(2) { + position: relative; + float :right; + margin-top : 90px; + margin-right : 80px; + background-color: lightblue; + width: 300px; + text-align: center; + + &:after { + position: absolute; + top: -100px; + left: -100px; + width: 100px; + height: 100px; + content : ''; + background: url(../images/dot_l.PNG); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 100%; + } + + &:before { + position: absolute; + top: -100px; + left: 300px; + width: 100px; + height: 100px; + content : ''; + background: url(../images/dot_r.PNG); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 100%; + } + + >a { + display: block; + font-size: 16px; + padding: 15px 50px; + background-color: $mainColor; + color: #fff; + + } + } + + >dl { + + >dt { + position: relative; + margin-bottom: 50px; + font-size: 25px; + + &::after { + position: absolute; + top: 40px; + left: 0; + width: 400px; + border: 1px solid $mainColor; + content: ''; + } + } + + >dd { + line-height: 1.5em; + font-size: 35px; + + &:nth-child(3) { + font-size: 15px; + color: #666666; + } + + } + + } + } + } + }//END + }//end of mainOverView + + .mainRND { + position: relative; + margin-bottom: 0px; + width: 100%; + height: 190px; + background: url(../images/www.jpg); + background-attachment: fixed; + background-size: cover; + background-position: 50% 50%; + background-repeat: no-repeat; + z-index: 0; + + + >h2 { + + &:after { + //display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 190px; + background-color: $mainColor2; + opacity: 0.4; + content: ''; + z-index: -1; + } + } + + >ul { + width: 1200px; + margin: 50px auto 0; + text-align: center; + color: #fff; + z-index: 10 !important; + + + >li { + font-size: 30px; + z-index: 10; + + &:last-child { + margin-top: 20px; + + >a { + padding: 10px 60px; + background-color: #777; + font-size: 15px; + color: #fff; + z-index: 9999; + transition: 0.3s; + + &:hover { + background-color: $mainColor; + } + } + } + } + } + }//end of mainRND + + + + + + +}//end of section + + +/* +******************************************** +**************index.html의 css************** +******************************************** +*/ + + +/*서브 페이지 레이아웃*/ + +.subBanner { + width: 100%; + height: 200px; + background: url(../images/company_b.jpg); + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; + + >.inner { + @include innerSet(1200px, 0 auto); + + >.subBannerInfo { + + + >ul { + margin-top : 90px; + float:right; + text-align: right; + width: 600px; + + >li { + color: #fff; + line-height: 1.9em; + cursor: default; + + &:nth-child(1) { + font-size: 28px; + + } + &:nth-child(2) { + position: relative; + font-size: 15px; + + &:after { + position: absolute; + top: -10px; + right : 0; + width: 200px; + border: 1px solid #fff; + content : ""; + } + + } + } + + } + } + + }//end of subBanner > inner +}//end of subBanner + + +.siteIndex { + padding: 7.5px 0; + border-bottom: 1px solid #dddddd; + + >.inner { + @include innerSet(1200px, 0 auto); + } + +}//end of siteIndex + +.sitemapContainer { + + @include innerSet(1200px, 0 auto); + + >ul { + width: 100%; + margin-top: 100px; + + >li { + float:left; + + &:nth-child(1) { + width: 300px; + + >dl{ + text-align: right; + + >dt { + font-size: 50px; + color: $mainColor; + } + >dd { + font-size: 25px; + color: #666; + + } + } + }//left sitemap + + &:nth-child(2) { + margin-bottom: 90px; + width: 900px; + + >dl { + position: relative; + float: left; + padding-left: 90px; + width: 300px; + height: 150px; + padding-bottom: 80px; + + &:after { + position: absolute; + bottom: 40px; + left: 90px; + content:""; + width: 300px; + height: 4px; + background-color: #ddd; + } + + + + &:nth-child(1) { + + + >dt { + + &:after { + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content:"Company"; + } + + + + } + } //회사소개 dl + + &:nth-child(2) { + + + >dt { + + &:after { + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content:"Business"; + } + + } + } //산업분야 dl + + &:nth-child(3) { + + + >dt { + + &:after { + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content:"Reference"; + } + + } + } //연구과제 dl + + &:nth-child(4) { + + + >dt { + &:after { + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content:"Contact Us"; + } + + } + } //기타 dl + + dt { + position: relative; + margin-bottom: 20px; + font-size: 25px; + font-weight: 600; + color: #000; + + &:after { + font-weight: 500; + } + &:before { + position: absolute; + top: 30px; + left: 0px; + width: 300px; + height: 3px; + background-color: $mainColor; + font-size: 50px; + content:""; + + } + + + } + dd { + position: relative; + margin-left: 35px; + line-height: 2em; + + + >a { + color: #000; + } + + } + } + + + }// sitemap menu + + }//end of sitemapContainer ul li + }//end of sitemapContainer ul + + + +}//end of sitemapContainer + + +@media screen and (max-width:768px) { // end of mainPage section css 768 + + section { + + >.mainBanner { + width: 100%; + height: 280px;//510px + background: url(../images/mvisual_02.jpg); + background-position: 50% 15%; + background-size: cover; + background-repeat: no-repeat; + + >.mainBannerCont { + width: 100%; + + >.inner { + @include innerSet(100%, 0 );// 1200px auto + + >ul { + margin-top : 0px;// 70px + + >li{ + float: inherit;;//left + height: 100%;//480px + width: 100%;//520px + text-align: center; + + &:nth-child(3) { + >dl { + dt { + margin-top: -40px; + text-indent: -99999px; + width: 100%; + height: 160px; + background-image: url(../images/dbnt_m.png); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: 80%; + } + } + } + + >dl { + margin-top: -50px; + color: #fff; + width: 100%; + padding: 10px 0px; + background-color: rgba(000,000,000,0.5); + + + >dt { + margin-bottom: 10px;//0px + font-size: 23px;//30px + font-weight: 600; + + } + + >dd { + line-height: 1.7em;//3.5px + font-size: 13px;//17px + font-weight: normal; + padding: 0 10px; + + + } + + } + + } + }//end of mainBanner > inner > ul + + }//end of mainBanner > inner + }//end of mainBannerCont + }//end of mainBanner + + >.mainIndustries { + width: 100%;//1200px + margin: 0 auto 0PX;//0 auto 90px + + >p { + position: relative; + padding-top : 80px; + text-align: center; + font-size: 18px; + color: #000; + + &:after { + position: absolute; + bottom: -20px; + left: 50%; + margin-left : -50px; + width: 100px; + height: 3px; + background-color: #000; + content: ""; + } + + } + + ul { + padding-top: 80px; + + >li { + overflow: hidden; + float: inherit;//left + width: 100%; + height: 200px;//300px + margin-left: 0px;//75px + border-radius: 0px;//300px + + + >a { + display: block; + height: 200px;//300px + transition: 0.3s; + + + + >dl { + height: 100%; + transform: translateY(50%); + text-align: center; + color: #fff; + + + >dt { + margin-top: -10px; + font-size: 20px; + + } + + >dd { + margin-bottom: 20px; + line-height: 1.9em; + transition: 0.3s; + + + &:nth-child(2) { + position: absolute; + top: -170px; + width: 100%; + height: 350px; + background-position: 50% 50%; + z-index: 0; + + + } + + + } + } + + } + + &:nth-child(1) { + background: url(../images/btn_main01.jpg); + background-position: 0% 0%; + background-repeat: no-repeat; + background-size: cover; + + + + dd { + &:last-child { + + } + + } + } + + &:nth-child(2) { + background: url(../images/asd_01.jpg); + background-position: 10% 100%; + background-repeat: no-repeat; + background-size: cover; + + dd { + &:last-child { + + } + + } + } + + &:nth-child(3) { + background: url(../images/tt.jpg); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + + dd { + &:last-child { + + } + + } + } + + + + }//end of mainIndustries > ul > li + + }//end of mainIndustries > ul + + }//end of mainIndustries + + + >.mainOverView { + margin-top : 100px; + padding: 60px 0; + background-color: #efefef; + + >.inner { + @include innerSet(1200px,0 auto ); + + >ul { + + >li { + float:left; + + &:nth-child(2) { + position: relative; + float :right; + margin-top : 90px; + margin-right : 80px; + background-color: lightblue; + width: 300px; + text-align: center; + + &:after { + position: absolute; + top: -100px; + left: -100px; + width: 100px; + height: 100px; + content : ''; + background: url(../images/dot_l.PNG); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 100%; + } + + &:before { + position: absolute; + top: -100px; + left: 300px; + width: 100px; + height: 100px; + content : ''; + background: url(../images/dot_r.PNG); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 100%; + } + + >a { + display: block; + font-size: 16px; + padding: 15px 50px; + background-color: $mainColor; + color: #fff; + + } + } + + >dl { + + >dt { + position: relative; + margin-bottom: 50px; + font-size: 25px; + + &::after { + position: absolute; + top: 40px; + left: 0; + width: 400px; + border: 1px solid $mainColor; + content: ''; + } + } + + >dd { + line-height: 1.5em; + font-size: 35px; + + &:nth-child(3) { + font-size: 15px; + color: #666666; + } + + } + + } + } + } + }//END + }//end of mainOverView + + .mainRND { + position: relative; + margin-bottom: 0px;//20px + width: 100%; + height: 200px;//230px + background: url(../images/www.jpg); + background-attachment: fixed; + background-size: cover; + background-position: 50% 50%; + background-repeat: no-repeat; + z-index: 0; + + + >h2 { + + &:after { + //display: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 200px; + background-color: $mainColor2; + opacity: 0.4; + content: ''; + z-index: -1; + } + } + + >ul { + width: 100%;//1200px + margin: 60px auto 0; + text-align: center; + color: #fff; + z-index: 10 !important; + + + >li { + font-size: 20px; + z-index: 10; + + &:last-child { + margin-top: 20px; + + >a { + padding: 10px 60px; + background-color: #777; + font-size: 15px; + color: #fff; + z-index: 9999; + transition: 0.3s; + + &:hover { + background-color: $mainColor; + } + } + } + } + } + }//end of mainRND + + + + + + + }//end of section + + + .subBanner { + width: 100%; + height: 250px;//변경 + background: url(../images/company.jpg); + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; + + >.inner { + @include innerSet(100%, 0); // 1200px 0 auto + + >.subBannerInfo { + + + >ul { + margin-top : 60px;//150px + float: inherit;;//right + text-align: center;//right + width: 100%;//600px + + >li { + color: #fff; + line-height: 1.9em; + cursor: default; + + &:nth-child(1) { + font-size: 30px;//50px + + } + &:nth-child(2) { + position: relative; + font-size: 15px; + padding: 0 90px;// 추가 + + &:after { + position: absolute; + top: -10px; + right : 50%;// 0 + transform: translateX(50%);//추가 + width: 200px; + border: 1px solid #fff; + content : ""; + } + + } + } + + } + } + + }//end of subBanner > inner + }//end of subBanner + + + .siteIndex { + padding: 7.5px 0; + text-align: center; + border-bottom: 1px solid #dddddd; + font-size: 13px; + + >.inner { + @include innerSet(100%, 0);//1200px 0 auto + } + + }//end of siteIndex + + + .sitemapContainer { + + @include innerSet(100%, 0); // 1200px auto + + >ul { + width: 100%; + margin-top: 100px; + + >li { + float: inherit; // left + + &:nth-child(1) { + width: 100%;// 300px + margin: 100px 0; //추가 + + >dl{ + text-align: center;//right + + >dt { + font-size: 50px; + color: $mainColor; + } + >dd { + font-size: 25px; + color: #666; + + } + } + }//left sitemap + + &:nth-child(2) { + margin-top: 50px;// 추가 + margin-bottom: 90px; + width: 100%;//900px + + >dl { + position: relative; + float: left; + padding-left: 0px;//90px + width: 100%;//300px + height: 150px; + padding-bottom: 80px; + + &:after { + position: absolute; + bottom: 40px; + left: 0px;//90px + content:""; + width: 100%;//300px + height: 4px; + background-color: #ddd; + } + + + + &:nth-child(1) { + + + + >dt { + + &:after { + display: none;//추가 + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content:"Company"; + } + + + + } + } //회사소개 dl + + &:nth-child(2) { + + + >dt { + + &:after { + display: none;//추가 + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content:"Business"; + } + + } + } //산업분야 dl + + &:nth-child(3) { + + + >dt { + + &:after { + display: none;//추가 + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content:"Research and Development"; + } + + } + } //연구과제 dl + + &:nth-child(4) { + + + >dt { + &:after { + display: none;//추가 + position: absolute; + top: 10px; + left: 100px; + font-size: 13px; + color: #777; + content:"Contact Us"; + } + + } + } //기타 dl + + dt { + position: relative; + text-align: center;//추가 + margin-bottom: 20px; + font-size: 25px; + font-weight: 600; + color: #000; + + &:after { + font-weight: 500; + } + &:before { + position: absolute; + top: 30px; + left: 0px; + width: 100%;// 300px + height: 3px; + background-color: $mainColor; + font-size: 50px; + content:""; + + } + + + } + dd { + position: relative; + margin-left: 0px;//35px + text-align: center;//추가 + line-height: 2em; + border-bottom: 1px solid #ddd; + + + >a { + color: #000; + } + + } + } + + + }// sitemap menu + + }//end of sitemapContainer ul li + }//end of sitemapContainer ul + + + + }//end of sitemapContainer + +}//end of mediaQuery + + + + + + + + + + + diff --git a/css/swiper.less b/css/swiper.less new file mode 100644 index 0000000..e474720 --- /dev/null +++ b/css/swiper.less @@ -0,0 +1,7 @@ +@import url('mixins.less'); +@import url('core.less'); +@import url('navigation.less'); +@import url('effects.less'); +@import url('zoom.less'); +@import url('scrollbar.less'); +@import url('preloader.less'); \ No newline at end of file diff --git a/css/swiper.min.css b/css/swiper.min.css new file mode 100644 index 0000000..6c6522f --- /dev/null +++ b/css/swiper.min.css @@ -0,0 +1 @@ +.swiper-container{margin-left:auto;margin-right:auto;position:relative;overflow:hidden;z-index:1}.swiper-container-no-flexbox .swiper-slide{float:left}.swiper-container-vertical>.swiper-wrapper{-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.swiper-wrapper{position:relative;width:100%;height:100%;z-index:1;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-transition-property:-webkit-transform;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.swiper-container-android .swiper-slide,.swiper-wrapper{-webkit-transform:translate3d(0,0,0);-moz-transform:translate3d(0,0,0);-o-transform:translate(0,0);-ms-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.swiper-container-multirow>.swiper-wrapper{-webkit-box-lines:multiple;-moz-box-lines:multiple;-ms-flex-wrap:wrap;-webkit-flex-wrap:wrap;flex-wrap:wrap}.swiper-container-free-mode>.swiper-wrapper{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out;margin:0 auto}.swiper-slide{-webkit-flex-shrink:0;-ms-flex:0 0 auto;flex-shrink:0;width:100%;height:100%;position:relative}.swiper-container-autoheight,.swiper-container-autoheight .swiper-slide{height:auto}.swiper-container-autoheight .swiper-wrapper{-webkit-box-align:start;-ms-flex-align:start;-webkit-align-items:flex-start;align-items:flex-start;-webkit-transition-property:-webkit-transform,height;-moz-transition-property:-moz-transform;-o-transition-property:-o-transform;-ms-transition-property:-ms-transform;transition-property:transform,height}.swiper-container .swiper-notification{position:absolute;left:0;top:0;pointer-events:none;opacity:0;z-index:-1000}.swiper-wp8-horizontal{-ms-touch-action:pan-y;touch-action:pan-y}.swiper-wp8-vertical{-ms-touch-action:pan-x;touch-action:pan-x}.swiper-button-next,.swiper-button-prev{position:absolute;top:50%;width:27px;height:44px;margin-top:-22px;z-index:10;cursor:pointer;-moz-background-size:27px 44px;-webkit-background-size:27px 44px;background-size:27px 44px;background-position:center;background-repeat:no-repeat}.swiper-button-next.swiper-button-disabled,.swiper-button-prev.swiper-button-disabled{opacity:.35;cursor:auto;pointer-events:none}.swiper-button-prev,.swiper-container-rtl .swiper-button-next{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");left:10px;right:auto}.swiper-button-prev.swiper-button-black,.swiper-container-rtl .swiper-button-next.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-prev.swiper-button-white,.swiper-container-rtl .swiper-button-next.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next,.swiper-container-rtl .swiper-button-prev{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23007aff'%2F%3E%3C%2Fsvg%3E");right:10px;left:auto}.swiper-button-next.swiper-button-black,.swiper-container-rtl .swiper-button-prev.swiper-button-black{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23000000'%2F%3E%3C%2Fsvg%3E")}.swiper-button-next.swiper-button-white,.swiper-container-rtl .swiper-button-prev.swiper-button-white{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23ffffff'%2F%3E%3C%2Fsvg%3E")}.swiper-pagination{position:absolute;text-align:center;-webkit-transition:.3s;-moz-transition:.3s;-o-transition:.3s;transition:.3s;-webkit-transform:translate3d(0,0,0);-ms-transform:translate3d(0,0,0);-o-transform:translate3d(0,0,0);transform:translate3d(0,0,0);z-index:10}.swiper-pagination.swiper-pagination-hidden{opacity:0}.swiper-container-horizontal>.swiper-pagination-bullets,.swiper-pagination-custom,.swiper-pagination-fraction{bottom:10px;left:0;width:100%}.swiper-pagination-bullet{width:8px;height:8px;display:inline-block;border-radius:100%;background:#000;opacity:.2}button.swiper-pagination-bullet{border:none;margin:0;padding:0;box-shadow:none;-moz-appearance:none;-ms-appearance:none;-webkit-appearance:none;appearance:none}.swiper-pagination-clickable .swiper-pagination-bullet{cursor:pointer}.swiper-pagination-white .swiper-pagination-bullet{background:#fff}.swiper-pagination-bullet-active{opacity:1;background:#007aff}.swiper-pagination-white .swiper-pagination-bullet-active{background:#fff}.swiper-pagination-black .swiper-pagination-bullet-active{background:#000}.swiper-container-vertical>.swiper-pagination-bullets{right:10px;top:50%;-webkit-transform:translate3d(0,-50%,0);-moz-transform:translate3d(0,-50%,0);-o-transform:translate(0,-50%);-ms-transform:translate3d(0,-50%,0);transform:translate3d(0,-50%,0)}.swiper-container-vertical>.swiper-pagination-bullets .swiper-pagination-bullet{margin:5px 0;display:block}.swiper-container-horizontal>.swiper-pagination-bullets .swiper-pagination-bullet{margin:0 5px}.swiper-pagination-progress{background:rgba(0,0,0,.25);position:absolute}.swiper-pagination-progress .swiper-pagination-progressbar{background:#007aff;position:absolute;left:0;top:0;width:100%;height:100%;-webkit-transform:scale(0);-ms-transform:scale(0);-o-transform:scale(0);transform:scale(0);-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left top}.swiper-container-rtl .swiper-pagination-progress .swiper-pagination-progressbar{-webkit-transform-origin:right top;-moz-transform-origin:right top;-ms-transform-origin:right top;-o-transform-origin:right top;transform-origin:right top}.swiper-container-horizontal>.swiper-pagination-progress{width:100%;height:4px;left:0;top:0}.swiper-container-vertical>.swiper-pagination-progress{width:4px;height:100%;left:0;top:0}.swiper-pagination-progress.swiper-pagination-white{background:rgba(255,255,255,.5)}.swiper-pagination-progress.swiper-pagination-white .swiper-pagination-progressbar{background:#fff}.swiper-pagination-progress.swiper-pagination-black .swiper-pagination-progressbar{background:#000}.swiper-container-3d{-webkit-perspective:1200px;-moz-perspective:1200px;-o-perspective:1200px;perspective:1200px}.swiper-container-3d .swiper-cube-shadow,.swiper-container-3d .swiper-slide,.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top,.swiper-container-3d .swiper-wrapper{-webkit-transform-style:preserve-3d;-moz-transform-style:preserve-3d;-ms-transform-style:preserve-3d;transform-style:preserve-3d}.swiper-container-3d .swiper-slide-shadow-bottom,.swiper-container-3d .swiper-slide-shadow-left,.swiper-container-3d .swiper-slide-shadow-right,.swiper-container-3d .swiper-slide-shadow-top{position:absolute;left:0;top:0;width:100%;height:100%;pointer-events:none;z-index:10}.swiper-container-3d .swiper-slide-shadow-left{background-image:-webkit-gradient(linear,left top,right top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(right,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(right,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(right,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to left,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-3d .swiper-slide-shadow-right{background-image:-webkit-gradient(linear,right top,left top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(left,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(left,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(left,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to right,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-3d .swiper-slide-shadow-top{background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(bottom,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(bottom,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(bottom,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to top,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-3d .swiper-slide-shadow-bottom{background-image:-webkit-gradient(linear,left bottom,left top,from(rgba(0,0,0,.5)),to(rgba(0,0,0,0)));background-image:-webkit-linear-gradient(top,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-moz-linear-gradient(top,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:-o-linear-gradient(top,rgba(0,0,0,.5),rgba(0,0,0,0));background-image:linear-gradient(to bottom,rgba(0,0,0,.5),rgba(0,0,0,0))}.swiper-container-coverflow .swiper-wrapper,.swiper-container-flip .swiper-wrapper{-ms-perspective:1200px}.swiper-container-cube,.swiper-container-flip{overflow:visible}.swiper-container-cube .swiper-slide,.swiper-container-flip .swiper-slide{pointer-events:none;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden;z-index:1}.swiper-container-cube .swiper-slide .swiper-slide,.swiper-container-flip .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-active .swiper-slide-active,.swiper-container-flip .swiper-slide-active,.swiper-container-flip .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-container-cube .swiper-slide-shadow-bottom,.swiper-container-cube .swiper-slide-shadow-left,.swiper-container-cube .swiper-slide-shadow-right,.swiper-container-cube .swiper-slide-shadow-top,.swiper-container-flip .swiper-slide-shadow-bottom,.swiper-container-flip .swiper-slide-shadow-left,.swiper-container-flip .swiper-slide-shadow-right,.swiper-container-flip .swiper-slide-shadow-top{z-index:0;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden;-ms-backface-visibility:hidden;backface-visibility:hidden}.swiper-container-cube .swiper-slide{visibility:hidden;-webkit-transform-origin:0 0;-moz-transform-origin:0 0;-ms-transform-origin:0 0;transform-origin:0 0;width:100%;height:100%}.swiper-container-cube.swiper-container-rtl .swiper-slide{-webkit-transform-origin:100% 0;-moz-transform-origin:100% 0;-ms-transform-origin:100% 0;transform-origin:100% 0}.swiper-container-cube .swiper-slide-active,.swiper-container-cube .swiper-slide-next,.swiper-container-cube .swiper-slide-next+.swiper-slide,.swiper-container-cube .swiper-slide-prev{pointer-events:auto;visibility:visible}.swiper-container-cube .swiper-cube-shadow{position:absolute;left:0;bottom:0;width:100%;height:100%;background:#000;opacity:.6;-webkit-filter:blur(50px);filter:blur(50px);z-index:0}.swiper-container-fade.swiper-container-free-mode .swiper-slide{-webkit-transition-timing-function:ease-out;-moz-transition-timing-function:ease-out;-ms-transition-timing-function:ease-out;-o-transition-timing-function:ease-out;transition-timing-function:ease-out}.swiper-container-fade .swiper-slide{pointer-events:none;-webkit-transition-property:opacity;-moz-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.swiper-container-fade .swiper-slide .swiper-slide{pointer-events:none}.swiper-container-fade .swiper-slide-active,.swiper-container-fade .swiper-slide-active .swiper-slide-active{pointer-events:auto}.swiper-zoom-container{width:100%;height:100%;display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-moz-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-moz-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;text-align:center}.swiper-zoom-container>canvas,.swiper-zoom-container>img,.swiper-zoom-container>svg{max-width:100%;max-height:100%;object-fit:contain}.swiper-scrollbar{border-radius:10px;position:relative;-ms-touch-action:none;background:rgba(0,0,0,.1)}.swiper-container-horizontal>.swiper-scrollbar{position:absolute;left:1%;bottom:3px;z-index:50;height:5px;width:98%}.swiper-container-vertical>.swiper-scrollbar{position:absolute;right:3px;top:1%;z-index:50;width:5px;height:98%}.swiper-scrollbar-drag{height:100%;width:100%;position:relative;background:rgba(0,0,0,.5);border-radius:10px;left:0;top:0}.swiper-scrollbar-cursor-drag{cursor:move}.swiper-lazy-preloader{width:42px;height:42px;position:absolute;left:50%;top:50%;margin-left:-21px;margin-top:-21px;z-index:10;-webkit-transform-origin:50%;-moz-transform-origin:50%;transform-origin:50%;-webkit-animation:swiper-preloader-spin 1s steps(12,end) infinite;-moz-animation:swiper-preloader-spin 1s steps(12,end) infinite;animation:swiper-preloader-spin 1s steps(12,end) infinite}.swiper-lazy-preloader:after{display:block;content:"";width:100%;height:100%;background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%236c6c6c'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E");background-position:50%;-webkit-background-size:100%;background-size:100%;background-repeat:no-repeat}.swiper-lazy-preloader-white:after{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg%20viewBox%3D'0%200%20120%20120'%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20xmlns%3Axlink%3D'http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink'%3E%3Cdefs%3E%3Cline%20id%3D'l'%20x1%3D'60'%20x2%3D'60'%20y1%3D'7'%20y2%3D'27'%20stroke%3D'%23fff'%20stroke-width%3D'11'%20stroke-linecap%3D'round'%2F%3E%3C%2Fdefs%3E%3Cg%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(30%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(60%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(90%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(120%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.27'%20transform%3D'rotate(150%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.37'%20transform%3D'rotate(180%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.46'%20transform%3D'rotate(210%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.56'%20transform%3D'rotate(240%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.66'%20transform%3D'rotate(270%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.75'%20transform%3D'rotate(300%2060%2C60)'%2F%3E%3Cuse%20xlink%3Ahref%3D'%23l'%20opacity%3D'.85'%20transform%3D'rotate(330%2060%2C60)'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")}@-webkit-keyframes swiper-preloader-spin{100%{-webkit-transform:rotate(360deg)}}@keyframes swiper-preloader-spin{100%{transform:rotate(360deg)}} \ No newline at end of file diff --git a/eng/RnD_deep.html b/eng/RnD_deep.html new file mode 100644 index 0000000..6b668d5 --- /dev/null +++ b/eng/RnD_deep.html @@ -0,0 +1,146 @@ + + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • REFERENCE
    • +
    • Provides diverse solutions with Innovative technology for customer satisfaction
    • +
    +
    +
    +
    + +
    +
    + REFERENCE 》 Deep Learning-based accident image detection system +
    +
    +
    + +

    >

    +
    + +
    + +
      +
    • + +
    • +
    • +
      +
      Deep Learning-based accident image detection system
      +
      + Deep-learning based accident image detection system detects moving & target objects within + CCTV surveillance range and automatically recognize and alert emergency situation such as + accidents, reverse driving and fire specified in the management guideline. Compared to computer + vision-based video analysis techniques, this AI based system is less influenced by weather or place and detects accidents with higher accuracy. +
      +
      +
        +
      • 첫 비디오
      • +
      • 두번째 비디오
      • +
      • 세번째 비디오
      • + +
      +
      +
      +
    • +
    + +
    +
    +
      +
    • 1) Technology Introduction : Deep Learning-based accident image detection system
    • +
    • + Object Detection is a research field that analyzes video information by computer instead of a + person. Object detection technology is used variously in our daily life including pedestrian + detection, vehicle and road sign recognition by analyzing CCTV video. Especially, in the field of + traffic flow monitoring, the nationwide road network using CCTV is constantly monitored. In some + major section, an accident recognition system is in operation to automatically detect and inform + unexpected situations such as traffic jams, collision and falling objects and so forth. Typical + accident detection systems are equipped with algorithms based on traditional vision technology, + but it is highly sensitive to changes in surrounding environment such as luminance and weather, + resulting in pre-detection and detection errors. To solve this problem, DBNtech developed an + accident detection system that can detect objects in video like humans in various environments + using Deep Learning-based object detection technology. In collaboration with KICT(KOREA + INSTITUTE of CIVIL ENGINEERING and BUILDING TECHNOLOGY), we have completed an accident + detection system optimized for various environments and have set demonstrate-installed and delivered the system on since 2019. +
    • +
    +
      +
    • 2) Related images
    • +
    • + 레티나넷 + SSD and YOLO +
    • +
    +
      +
    • 3) Application of Deep Learning-based Object detection
    • +
    • +
      +
      A. Detection of unusual event (accident) through CCTV image analysis
      +
      +
      + 1. Detection of stop(or collision) and reverse driving
      + 2. Pedestrian detection
      + 3. Fire and smoke detection
      +
      +
      +
      +
      B. Character detection in images
      +
      +
      + 1. Card number recognition
      + 2. Vehicle’s license plate recognition
      +
      +
      +
      +
      C. Object recognition in space
      +
      +
      + 1. Product recognition for unattended store payment system
      + 2. Automatic inventory check-up in refrigerator
      +
      +
      +
      +
      D. Behavioral pattern analysis
      +
      +
      + 1. Human motion tracking
      + 2. Calculation of human’s action radius
      +
      +
      +
    • +
    +
    + +
    + +
    + +
    + +
    + + +
    + + + \ No newline at end of file diff --git a/eng/RnD_koreaRoad.html b/eng/RnD_koreaRoad.html new file mode 100644 index 0000000..7060865 --- /dev/null +++ b/eng/RnD_koreaRoad.html @@ -0,0 +1,106 @@ + + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • REFERENCE
    • +
    • Provides diverse solutions with Innovative technology for customer satisfaction
    • +
    +
    +
    +
    + +
    +
    + REFERENCE 》 Road sign management/guide system +
    +
    +
    + +

    <

    +
    + +
    + +
      +
    • +
    • +
      +
      Road sign management system
      +
      + Road sign management system is to manage road signs and analyze it for the appropriateness of location and guide information. Through review/supplement application and various statistics function, it can be used for overall understanding of road sign information status and a basis of policy decision. In addition, in order to properly manufacture, install and maintain road signs, road sign designs are standardized by each type so that the systematic and reasonable road sign automatic design program(RoadGuider) is developed. (www.roadsign.go.kr) +
      +
      +
        +
      • +
      • +
      • +
      +
      +
      +
    • +
    + +
    +
    +
      +
    • 1) Technology Introduction : Road sign system(management system & guide system)
    • +
    • + Road sign is an important road attachment that maximizes the efficiency of road use as well as securing safe and smooth road traffic by providing directions, distances, route guide and other information to the road user such as the driver of the vehicle. The road sign system(management system & guide system) is a system that can perform and query the overall management of road signs operated by the road sign operation center of KOREA INSTITUTE of CIVIL ENGINEERING and BUILDING TECHNOLOGY. DBNtech conducts the maintenance of the system & the improvement of functions according to the diverse needs of the users for the smooth operation of the road sign system, and we also fulfill the renewal of the road network map which serves as the basis for system operation. In particular, we have advanced the road sign system to a linear-based management level and have developed the system to support decision making on reinforcement of analytical functions utilizing linearity and new road sign design. The road sign system divided into a road sign management system (www.korearoadsign.go.kr), which enables 300 road sign management institutions to input and manage road signs and a road sign guide system (www.roadsign.go.kr) where ordinary people can search and inquiry road signs at all the times to provide service. +
    • +
    • 2) Linear-based management system
    • +
    • + A linear-based road sign system is a system that links all road sign data to a line (route) of the road and manages the signs on a route basis. The advantage of a linear-based system is that it automatically links all the signs to the linear information on the road, by matching consistent information from the road linear information, so it can improve error elimination & integrity and it is possible to distinguish between up-way and down-way according to the result of patch search and to ensure consistent data extraction. + +
    • +
    • 3) Detection function of a road sign with error
    • +
    • + Detection of a road sign with an error is a function that allows local staff to more granularly check the list of the road signs they manage to detect potential errors such as road type, road number, road name, management institution, unknown and so on. A wrong road sign is displayed on the screen with the combination of red question mark icons and gray icons so that they can be distinguished from existing road signs. Also users can enter the management institution, road type, route number, and administrative area as search criteria to obtain the list of road signs including errors they want and the management function of wrong road signs has been enhanced by adding the search function of a road sign with an error according to each administrative area.
      + +
    • +
    • 4) Decision support system
    • +
    • + If you want to create a new road sign, this function will automatically show not only a guide name but also sign standard, installation location and so on. Based on the function, it can inspect a guide name and sign standard from existing input signs using road linear information. In addition, the functions to display the surrounding distance at intersections and determine if the location of the road sign is appropriate within that distance can also be more accurately calculated with the road linear information.
      + +
    • + +
    • 5) Road sign design program(RoadGuider)
    • +
    • + In order to properly manufacture, install, and maintain road signs, an in-depth review and implementation should be carried out from the planning and design stages according to relevant laws and regulations. Therefore, RoadGuider, a road sign design program, was developed as a program to standardize a road signs design by type to establish a systematic and rational road guide system. In addition to road signs of existing guide names, RoadGuider applies the basic form and system of road signs, so the road management officials who produce, install and manage road signs can create and manage road signs more conveniently and systematically.
      + + +
    • +
    + +
    + +
    + +
    + +
    + +
    + + +
    + + + \ No newline at end of file diff --git a/eng/RnD_lunar.html b/eng/RnD_lunar.html new file mode 100644 index 0000000..a869b97 --- /dev/null +++ b/eng/RnD_lunar.html @@ -0,0 +1,115 @@ + + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • REFERENCE
    • +
    • Provides diverse solutions with Innovative technology for customer satisfaction
    • +
    +
    +
    +
    + +
    +
    + REFERENCE 》 Automatic detection system of craters on the Lunar surface +
    +
    +
    + +
      +
    1. <
    2. +
    3. >
    4. +
    +
    + +
    + +
      +
    • +
    • +
      +
      Automatic detection system of craters on the Lunar surface
      +
      + This system uses Deep-learning image recognition technology to recognize the lunar ground image objects and automatically detect craters. As deep learning-based object recognition technique learns DEM image with shading relief and a large number of unlabeled craters can be detected, so it contributes to securing high-performance terrain object image processing and automatic statistical technology in space construction. +
      +
      +
        +
      • +
      • +
      • +
      +
      +
      +
    • +
    + +
    +
    +
      +
    • 1) Technology Introduction : Automatic detection system of craters on the Lunar surface
    • +
    • + Detection of craters on the lunar surface is one of the most important research areas in aerospace. Traditionally, detecting craters on the lunar surface has been determined by experts’ visual check-up with high-resolution DEM (Digital Elevation Model) images. However, the results of the crater detection varied among experts so that it was difficult to maintain the reliability and consistency of the results. DBNtech conducted a study on automatic crater detection system using Deep Learning-based object detection technology as a consignment project of KICT(KOREA INSTITUTE of CIVIL ENGINEERING and BUILDING TECHNOLOGY). Using various techniques such as "Hill Shade" techniques as a preprocess instead of "DEM images" that are difficult to distinguish by the naked eye, we improved object detection performance of the Deep-learning model. As a result, not only was it possible to detect the large and small craters more precisely, but also a large number of craters that could not be detected with the naked eye could be detected. The result of this study can be also applied in other areas such as construction and transportation infrastructure using Deep-learning based object recognition in addition to space construction, and will contribute to revitalizing extreme environmental construction technologies and creating new markets related to future space exploration. +
    • +
    +
      +
    • 2) Test Result
    • +
    • + 레티나넷 + SSD and YOLO + SSD and YOLO +
    • +
    +
      +
    • 3) Application of Deep Learning-based object detection
    • +
    • +
      +
      A. Surface condition analysis of SOC facilities based on image
      +
      +
      + 1. Recognition of conditions such as deterioration, cracking, breakage and etc.
      + 2. Possible to identify the position and size of damage in image
      +
      +
      +
      +
      B. Character detection in images
      +
      +
      + 1. Character detection in images
      + 2. Fault diagnosis based on Deep-learning(video/sound)
      +
      +
      +
    • +
    +
    + +
    + +
    + +
    + +
    + + +
    + + + \ No newline at end of file diff --git a/eng/RnD_module.html b/eng/RnD_module.html new file mode 100644 index 0000000..6a23a0c --- /dev/null +++ b/eng/RnD_module.html @@ -0,0 +1,155 @@ + + + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • REFERENCE
    • +
    • Provides diverse solutions with Innovative technology for customer satisfaction
    • +
    +
    +
    +
    + +
    +
    + REFERENCE 》 Liquefaction modeling and 3D analysis module +
    +
    +
    + +
      +
    1. <
    2. +
    3. >
    4. +
    +
    + +
    + +
      +
    • +
    • +
      +
      liquefaction modeling and 3D analysis module based on Drilling information
      +
      + Development of liquefaction analysis basic data modeling and 2/3D liquefaction analysis map generation module for the efficient extraction of drilling information. The liquefaction analysis and visualization information obtained through the developed module can be used as a liquefaction damage prediction system to build a linkage and utilization system with other systems such as earthquake disaster. +
      +
      +
        +
      • +
      • +
      • +
      +
      +
      +
    • +
    + +
    +
    +
      +
    • 1) Technology Introduction : liquefaction modeling and 3D analysis module
    • +
    • + The liquefaction phenomenon has been officially confirmed in recent earthquakes in Pohang. Liquefaction is the phenomenon of loss of rigidity and shearing strength when the soil is stressed. In general, when liquefaction occurs, a parts of the water and sand can be ejected over the ground with creating space, so there is a risk of road erosion or sinkholes. Therefore, there is a growing need to produce a liquefaction risk maps in Korea, and this study extracts information related to national drilling information for the map and developed modules for basic data modeling and three-dimensional analysis based on the drilling information. +
    • +
    • 2) interpolation
    • +
    • + Interpolation (or spatial interpolation) is a method of building new data points using known data points. When you need statistics on space, the best way is to acquire the data you need at every point. However, it is practically impossible to get the desired value at all points due to problems such as cost and time. Therefore, after selecting a number of specific points to obtain observation value, this value data is used to predict the value of the points to be known, and interpolation is widely used in this process. The system provides six typical interpolation methods as following. +
    • +
    +
      +
    • 3) Type of interpolation
    • +
    • +
      +
      A) Radial Basis Function(RBF)
      +
      + It is a proposed model for the interpolation of multivariate data, so it is easy to generate compared with kriging and it expresses a system with a strong nonlinearity well, but predictive performance reacts sensitively. +
      +
      +
      +
      B) Natural Neighbor interpolation
      +
      + It is the simplest interpolation based on the Voronoi tessation of discrete spatial sets and shows relatively close approximations. +
      +
      +
      +
      C) Inverse Distance Weight (IDW)
      +
      + A method for determining the value of a new cell using linearly coupled weights from a nearby point. It is called the Inverse Distance Weight because the closer the distance is, the higher the weight is applied. +
      +
      +
      +
      D) kriging(Triangulated Irregular Network]
      +
      + It is a geo-statistical method that a linear combination of known data is used to estimate the value of the property at the point of interest. This method assumes the value by linearly combining the measured values of the surrounding with a statistical method. + When estimating the value, it reflects not only the distance from the measured value but also the correlation strength between neighboring values. It requires a large amount of calculation, but relatively accurate. +
      +
      +
      +
      E) Triangulated Irregular Network, TIN
      +
      + It is relatively suitable for small areas by connecting all points in a triangle to calculate values within the triangle. +
      +
      +
      +
      F) Spline interpolation
      +
      + Connection polynomials that gradually apply polynomials to subset of data points are called spline functions. Functions generally change smoothly, but sometimes rapidly in certain areas. Spline functions provide a good approximation to the behavior of locally and rapidly changing functions. +
      +
      +
    • +
    • + +
    • +
    +
      +
    • 4) Visualization
    • +
    • +
      +
      A. Surface Visualization
      +
      +
      + The surface visualization function visualizes the ground resistance value R corrected at regular intervals. When you click on the ground resistance surface visualization, the screen that the ground resistance value surface is visualized is output as shown in the picture. +
      +
      +
      +
      B. 3D Visualization
      +
      +
      + 3D visualization is a function that makes a modeling of the 3D resistance value based on the ground resistance 2D analysis result and shows it in three dimensions. The screen shown can be enlarged/ reduced/rotated and it supports a Legend for each resistance value to help visualization. The following is a conceptual diagram that visualizes 2D analysis results in 3D cube format. +
      +
      +
    • +
    +
    + +
    + +
    + +
    + +
    + + +
    + + + \ No newline at end of file diff --git a/eng/business01.html b/eng/business01.html new file mode 100644 index 0000000..5750521 --- /dev/null +++ b/eng/business01.html @@ -0,0 +1,60 @@ + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • BUSINESS
    • +
    • DBNtech is a human-centered company that pursues human life and happiness.
    • +
    +
    +
    +
    + +
    +
    + + BUSINESS 》 AI & BigData +
    +
    + +
    + + + +
    +

    >

    +
    +
      +
    • AI & BigData
    • +
    • + Development of system engine for real-time object detection and type analysis of Deep-learning based CCTV video +
    • +
    • + Development of accident detection system using Deep-learning technology through self-learning +
    • +
    • + Development of status monitoring system for SOC facilities based on Deep-learning image processing and consulting for ongoing operation support +
    • +
    • + Development of big data processing system for customized document based on machine-learning +
    • +
    + +
    + +
    + + + +
    +
    + + + \ No newline at end of file diff --git a/eng/business02.html b/eng/business02.html new file mode 100644 index 0000000..e5fe889 --- /dev/null +++ b/eng/business02.html @@ -0,0 +1,62 @@ + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • BUSINESS
    • +
    • DBNtech is a human-centered company that pursues human life and happiness.
    • +
    +
    +
    +
    + +
    +
    + BUSINESS 》 Smart SOC +
    +
    + +
    + + + +
    +
      +
    1. <
    2. +
    3. >
    4. +
    +
    +
      +
    • Smart SOC
    • +
    • + Development of smart SOC support technology using Big Data, high speed Network and DNA technology of AI (Artificial intelligence) +
    • +
    • + Video monitoring and status data processing of various SOC facilities(road, slope, tunnel, bridge and etc.) based on ICT +
    • +
    • + Development of SOC innovation technology utilizing intelligent technology to protect citizens from disaster and various accidents +
    • +
    • + Development of various solutions for building a smart safety society +
    • +
    + +
    + +
    + + + +
    +
    + + + \ No newline at end of file diff --git a/eng/business03.html b/eng/business03.html new file mode 100644 index 0000000..7651e23 --- /dev/null +++ b/eng/business03.html @@ -0,0 +1,64 @@ + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • BUSINESS
    • +
    • DBNtech is a human-centered company that pursues human life and happiness.
    • +
    +
    +
    +
    + +
    +
    + BUSINESS 》 IT Service +
    +
    + +
    + + +
    +

    <

    +
    +
      +
    • IT Service
    • +
    • + Building and operating systems and platforms for SOC, transportation, safety and service sector. +
    • + +
    • + Online platforms implementation and operation such as e-Commerce, SNS, ERP and enterprise support solutions +
    • + +
    • + Network and video integrated security management service +
    • + + +
    • + Technology transfer of new technology, tools and experts through information system outsourcing (ITO) +
    • +
    + +
    + +
    + + + +
    +
    + + + \ No newline at end of file diff --git a/eng/company_01.html b/eng/company_01.html new file mode 100644 index 0000000..5ddff55 --- /dev/null +++ b/eng/company_01.html @@ -0,0 +1,207 @@ + + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • COMPANY
    • +
    • DBNtech constantly pursues change and innovation
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 Introduction +
    +
    +
    + +

    >

    + +
      +
    • + Thank you for visiting DBNtech, value Innovation leading company to create future value +
    • +
    • + Founded on January 5 2018,
      + DBNtech is specialized in developing next-generation technology and solution for image analysis of moving objects based on Deep-learning and Big-data technology.
      + Through analysis and real-time linkage of massive CCTV big data collected from a public SOC (Social Overhead Capital), we conduct the provision of technical information service for the safety of the people, facility management and intelligent information realization.
      + We aim to contribute to the safer and more convenient world through the development and application of intelligent information technology using artificial intelligence, a core technology in the 4th Industrial Revolution era and to fulfill its role as a human-centered human technology company seeking to improve human life. + All of the executives and employees +
    • +
    + +
    +
    +
      +
    • +
      +
      디비엔텍 로고
      +
      Deeplearning BigData Next Technology
      +
      DBNtech
      +
      +
    • +
    + +
      + +
    • +
      +
      Address
      +
      Establish
      +
      Business
      +
      Certificate
      +
      TEL
      +
      FAX
      +
      E-mail
      +
      +
    • +
    • +
      +
      Robot Tower, No. 1205, 155-11, Robot land-ro, Seo-gu, Incheon
      +
      January 05, 2018
      +
      AI (Artificial intelligence), Video big data, Smart SOC, IT Service
      +
      Acquisition of a research institute / Venture business certificate
      +
      032-721-5670
      +
      032-721-5680
      +
      ahn@dbnt.co.kr
      +
      +
    • +
    + + + +
    + +
    +
    + +
    + +

    Organization

    + +
    + + + + + +
    + + + + + \ No newline at end of file diff --git a/eng/company_02.html b/eng/company_02.html new file mode 100644 index 0000000..27ec65b --- /dev/null +++ b/eng/company_02.html @@ -0,0 +1,314 @@ + + + + + +
    +

    Start of Content

    +
    + + + +
    +
    +
      +
    • COMPANY
    • +
    • DBNtech constantly pursues change and innovation
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 History +
    +
    +
    + + +
      +
    1. <
    2. +
    3. >
    4. +
    + +

    History

    + +
    +
    +

    2020

    +
      +
    • +
      +
      +
        +
      • 03월.
      • +
      • NIPA AI voucher Support business Supplier Registration
      • +
      +
        +
      • 01월.
      • +
      • KCG(Korea Coast Guard) Cyber foreign affairs System Maintenance
      • +
      +
      +
      +
    • +
    +
    +
    +

    2019

    +
      +
    • +
      +
      +
        +
      • 12월.
      • +
      • Implementing a TADs System : Deokcheon Tunnel, Chungcheongbuk-do Road Management Office
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 11월.
      • +
      • R&D Service Industry Registration (No. 20192625)
      • +
      +
      +
      +
        +
      • 11월.
      • +
      • Winning Innovative Start-up project (Development of Deep Learning-based Day&Night Incident Control Support System and Control Staff-led Growth Control Module)
      • +
      +
      +
      +
        +
      • 11월.
      • +
      • Participation in the Smart Construction Tech & Safety Expo 2019 (with KCC Engineering&Construction)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 09월.
      • +
      • Participation in the International Road & Traffic Expo 2019
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 08월.
      • +
      • Building relocation to secure additional research facilities (Robot Tower, No. 905~906, 155-11, Robot Land-ro, Seo-gu, Incheon, Republic of Korea)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 07월.
      • +
      • Research project from KICT (Development of a Program for Building Liquefied Risk Map Based on Ground Amplification GIS Analysis Map and LPI_LSN)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 06월.
      • +
      • Launch TADs system pilot service : Daritjae Tunnel, Chungju National Territory Management Office + *TADs(Tunnel Accident Detection system)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 03월.
      • +
      • Research project from KICT Creating Deep Learning Codes and Labeling Images for Learning for Automatic Recognition of Major Objects and Automatic Classification of Interested Areas in the Moon Local Images)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 02.
      • +
      • Acquisition of a certificate for an affiliated research institute (No. 2019110685)
      • +
      +
      +
      +
        +
      • 02.
      • +
      • Program Registration (a performance improving system of Deep-learning model inference for object recognition through feature value enhancement algorithm)
      • +
      +
      +
      +
    • +
    +
    +
    +

    2018

    +
      +
    • +
      +
      +
        +
      • 11.
      • +
      • + Conclusion of cooperation as an official family company with KICT(KOREA INSTITUTE of CIVIL ENGINEERING and BUILDING TECHNOLOGY) +
      • +
      +
      +
      +
        +
      • 11.
      • +
      • Technology transfer agreement with KITC(KOREA INSTITUTE of CIVIL ENGINEERING and BUILDING TECHNOLOGY)
      • +
      +
      +
      +
        +
      • 11.
      • +
      • technology development program for Start-up growing
        (Development of automatic recognition performance enhancement technology for traffic accident in CCTV video under harsh condition)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 07.
      • +
      • Building relocation to secure research facilities(18.07.29 Robot Tower, No. 1205, 155-11, Robot land-ro, Seo-gu, Incheon, Republic of Korea)
      • +
      +
      +
      +
        +
      • 07.
      • +
      • Acquisition of venture business Certificate (No. 20180401697)
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 06.
      • +
      • Selected as the candidate to be supported for leading venture-linked start-up support program in 2018
      • +
      +
      +
      +
        +
      • 06.
      • +
      • Confirmation of the re-leaping fund for technology assessment loan company-Korea SMEs and startups agency
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 05.
      • +
      • + Research project from KICT (Deap-learning code creation & Big data implementation for object recognition of the lunar ground image) +
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 03.
      • +
      • + Program Registration (machine learning-based big data analysis system) +
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 02.
      • +
      • + Acquisition of the Female company certificate(Incheon Regional Small and Medium Business Administration : No. 0116-2018-01732) +
      • +
      +
      +
      +
    • +
    • +
      +
      +
        +
      • 01.
      • +
      • Corporate establishment, Establishment of DBNtech (Corporate registration: 120111 -0914970)
      • +
      + +
      +
      +
        +
      • 01.
      • +
      • Business registration (NTS Bukincheon District Office : 704 - 88 – 00959)
      • +
      +
      +
      +
        +
      • 01.
      • +
      • SMB identification Certificate (Ministry of SMEs and Startups : 0010 - 2018 -0001954)
      • +
      +
      +
      +
        +
      • 01.
      • +
      • Software provider registration (Korea Software Industry Association : B18 – 160654)
      • +
      +
      +
      +
        +
      • 01.
      • +
      • Acquisition of direct production certificate (Korea Federation of SMEs : 2018 - 0071 – 03760)
      • +
      +
      +
      +
        +
      • 01.
      • +
      • Registration of public bidding qualification for the country
      • +
      +
      +
      +
        +
      • 01.
      • +
      • Acquisition of the certificate for exclusive research and development department (Korea Industrial Technology Association : No. 2018150584)
      • +
      +
      +
      +
    • +
    +
    +
    + + + +
    +
    + + + + \ No newline at end of file diff --git a/eng/company_03.html b/eng/company_03.html new file mode 100644 index 0000000..0c0c3fa --- /dev/null +++ b/eng/company_03.html @@ -0,0 +1,116 @@ + + + + +
    +

    Start of Content

    +
    + + + +
    +
    +
      +
    • COMPANY
    • +
    • DBNtech constantly pursues change and innovation
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 Certificate +
    +
    +
    + +

    <

    + +
    +
      +
    • + Certificate +
    • +
    +
    +
    +
      +
    • +
      +
      벤처기업확인서 사진
      +
      Venture Business certificate
      +
      +
    • +
    • +
      +
      기업부설연구소 사진
      +
      R&D Center Certificate
      +
      +
    • +
    • +
      +
      SW사업자신고확인서 사진
      +
      SW Operator Report Certificate
      + +
      +
    • +
    +
    +
    +
      +
    • +
      +
      직접생산확인증명서 사진
      +
      Direct Production Certificate
      +
      +
    • +
    • +
      +
      중소기업확인서 사진
      +
      SMB Identification Certificate
      +
      +
    • +
    • +
      +
      경쟁입찰참가자격증등록 사진
      +
      Registration of Participation in Competitive Bidding
      +
      +
    • +
    +
    +
    +
      +
    • +
      +
      여성기업확인서 사진
      +
      Female Company Certificate
      +
      +
    • +
    • +
      +
      프로그램등록증 사진
      +
      Program Certificate
      +
      +
    • +
    • +
      +
      프로그램등록증 사진
      +
      Program Certificate
      + +
      +
    • +
    +
    +
    + + +
    + + + +
    +
    + + + \ No newline at end of file diff --git a/eng/company_04.html b/eng/company_04.html new file mode 100644 index 0000000..fae256f --- /dev/null +++ b/eng/company_04.html @@ -0,0 +1,146 @@ + + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • COMPANY
    • +
    • DBNtech constantly pursues change and innovation
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 RECRUITMENT +
    +
    +
    + +
    +
      +
    • Recruit
      ment
    • +
    • DBNtech looks for
      creative and professional talent.
    • +
    +
    +
    +

    The Right People for DBNtech

    +
      +
    • A challenging person who always seeks newness
    • +
    • A person who can change ideas and perceptions
    • +
    • A person with tenacity and passion to achieve a challenge
    • +
    • A person who is faithful to every assignment
    • +
    • A person who can collaborate smoothly with team members
    • +
    • A person who is capable of working with expertise
    • +
    + +
    +
    +

    Employment Information

    + +
    +
      +
    • +
      +
      DBNtech
      +
      R&D Division
      +
      Software Engineer / Researcher
      +
      +
    • +
    • img
    • +
    +
      +
    • +
      +
      DBNtech
      +
      System Development Division
      +
      Software Engineer / Programmer
      +
      +
    • +
    • img
    • +
    +
    + +
    +

    X

    +
      +
    • +
      +
      Software Engineer/Researcher
      +
      R&D Division
      +
      +
    • +
    • +
        +
      • Qualifications & Preferences
      • +
      • +
        +
        Major : Engineering
        +
        Degree : Bachelor or above
        +
        ■ Python, Deep-learning Framework(Tensorflow) Expert (Required)
        +
        ■ Deep-learning Model Design/Development(CNN, Object Detection related) (Required)
        +
        ■ More than 1 year of experience in developing algorithms based on Machine-learning or Deep-learning (Preferred)
        +
        ■ Open data set analysis experience such as Kaggle (Preferred)
        +
        ■ Information processing engineer certificate holder (Preferred)
        +
        +
      • +
      +
    • +
    +
      +
    • +
      +
      Software Engineer/Programmer
      +
      System Development Division
      +
      +
    • +
    • +
        +
      • Qualifications & Preferences
      • +
      • +
        +
        Major : Engineering
        +
        Degree : Diploma or above
        +
        ■ S/W Development : ASP, Java, Spring, JSP, C, C⁺⁺, MFC
        +
        ■ Server Operations : Windows Server, Linux, IIS, Tomcat
        +
        ■ Database : Oracle, MySql
        +
        +
      • +
      +
    • +
    + +
    +
    + +
    +

    Employment Notice

    +
      +
    • Recruitment Schedule : Regular Recruitment
    • +
    • Recruitment procedure : 1st(Documents) → 2nd(Interview) → final acceptance
    • +
    • Welfare benefits : Support for family events, job skill improvement, book purchase, in-company fellowship and etc.
    • +
    +
    + + +
    +
    + + + + \ No newline at end of file diff --git a/eng/contact_us.html b/eng/contact_us.html new file mode 100644 index 0000000..317c775 --- /dev/null +++ b/eng/contact_us.html @@ -0,0 +1,62 @@ + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • CONTACT US
    • +
    • -
    • +
    +
    +
    +
    + +
    +
    + CONTACT US +
    +
    +
    + +

    contact us

    + +
    +
      + +
    • DBNtech
    • +
    • RobotTower, No. 1205, 155-11, Robot land-ro, Seo-gu, Incheon, Republic of Korea
    • +
    • + ahn@dbnt.co.kr +
    • +
    • + 032)721.5670 +
    • +
    • + 032)721.5680 +
    • +
    +
    + +
    +
    +
    + +
    +
    + + + + + \ No newline at end of file diff --git a/eng/css/common.css b/eng/css/common.css new file mode 100644 index 0000000..d858f3b --- /dev/null +++ b/eng/css/common.css @@ -0,0 +1,1752 @@ +@charset "UTF-8"; +.clearfix { + *zoom: 1; } + .clearfix:after { + display: block; + clear: both; + content: ''; } + +.sr_only { + position: absolute; + left: -99999px; } + +.inner { + width: 1200px; + margin: 0 auto; } + +@media screen and (max-width: 768px) { + .inner { + width: 100%; } } +#wrap { + width: 100%; + background-color: #f1f1f1; } + +.upArrow { + display: none; + position: fixed; + bottom: 50px; + right: 50px; + width: 40px; + height: 40px; + background-color: #263d78; + border-radius: 50px; + cursor: pointer; + z-index: 9000; } + .upArrow:after { + position: absolute; + top: 7px; + left: 50%; + transform: translateX(-50%); + width: 22px; + height: 22px; + background-image: url(../images/up_arrow.png); + background-position: 50% 50%; + content: ''; } + +body { + overflow-x: hidden; } + +h3 { + font-size: 30px; } + +::-webkit-scrollbar { + width: 8px; + height: 8px; + border: 3px solid #fff; } + +::-webkit-scrollbar-button:start:decrement, +:-webkit-scrollbar-button:end:increment { + display: block; + height: 10px; + background: url("./images/bg.png") #efefef; } + +::-webkit-scrollbar-track { + background: #efefef; + -webkit-border-radius: 10px; + border-radius: 10px; + -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.2); } + +::-webkit-scrollbar-thumb { + height: 50px; + width: 50px; + background: rgba(0, 0, 0, 0.2); + -webkit-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: inset 0 0 4px rgba(0, 0, 0, 0.1); } + +/*------- standard set -----------*/ +header { + position: fixed; + top: 0; + width: 100%; + height: 70px; + background-color: rgba(0, 0, 0, 0.3); + z-index: 99999; + transition: .3s; } + header > .inner { + position: relative; } + header > .inner > .toggle { + display: none; + position: absolute; + top: 0; + right: 0; + width: 70px; + height: 70px; + cursor: pointer; + text-indent: -99999px; + background-image: url(../images/toggle.png); } + header > .inner > h1 { + position: absolute; + width: 200px; + height: 70px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 50%; } + header > .inner > h1 > a { + display: block; + width: 100%; + height: 100%; } + header > .inner > .gnb { + position: absolute; + right: 0; + width: 500px; } + header > .inner > .gnb > ul > li { + float: left; + width: 100px; } + header > .inner > .gnb > ul > li > a { + display: block; + height: 70px; + font-size: 15px; + font-weight: 600; + color: rgba(255, 255, 255, 0.6); + line-height: 70px; + text-align: center; } + header > .inner > .gnb > ul > li > a.on { + color: white; } + header > .inner > .gnb > ul > li > a:hover { + color: white; } + header > .inner > .gnb > ul > li > .sub { + position: absolute; + bottom: -40px; + width: 100%; + z-index: 5000; + display: none; } + header > .inner > .gnb > ul > li > .sub.sub01 { + position: absolute; + left: 0; } + header > .inner > .gnb > ul > li > .sub.sub01 > .subcontainer > ul { + margin-left: 30px; } + header > .inner > .gnb > ul > li > .sub.sub01 > .subcontainer > ul > li { + margin-left: 20px; } + header > .inner > .gnb > ul > li > .sub.sub02 { + position: absolute; + left: 0; } + header > .inner > .gnb > ul > li > .sub.sub02 > .subcontainer > ul > li { + margin-left: 20px; } + header > .inner > .gnb > ul > li > .sub.sub03 { + position: absolute; + left: 0; } + header > .inner > .gnb > ul > li > .sub.sub03 > .subcontainer > ul > li { + margin-left: 70px; } + header > .inner > .gnb > ul > li > .sub.sub04 { + position: absolute; + left: 0; } + header > .inner > .gnb > ul > li > .sub.sub04 > .subcontainer > ul { + margin-left: 300px; } + header > .inner > .gnb > ul > li > .sub.sub04 > .subcontainer > ul > li { + margin-left: 20px; } + header > .inner > .gnb > ul > li > .sub > .subcontainer > ul > li { + height: 40px; + line-height: 40px; + float: left; + font-size: 16px; + margin-left: 20px; } + header > .inner > .gnb > ul > li > .sub > .subcontainer > ul > li > a { + display: block; + font-weight: 600; + color: #333; } + header > .inner > .gnb > ul > li > .sub > .subcontainer > ul > li > a:hover { + color: #ffc700; } + header > .inner > .gnb .lang { + position: absolute; + top: 0; + right: 5px; + width: 80px; + height: 70px; + text-align: center; + line-height: 70px; + color: rgba(255, 255, 255, 0.7); + font-weight: 600; + cursor: pointer; } + header > .inner > .gnb .lang:hover { + color: white; } + header > .inner > .gnb .lang > ul { + display: none; + width: 100%; + background-color: rgba(0, 0, 0, 0.5); } + header > .inner > .gnb .lang > ul > li { + line-height: 40px; } + header > .inner > .gnb .lang > ul > li:hover a { + color: #ffc700; } + header > .inner > .gnb .lang > ul > li.on a { + color: #ffc700; } + header > .inner > .gnb .lang > ul > li > a { + color: #fff; } + header > .sub_bg { + display: none; + position: absolute; + top: 70px; + width: 100%; + height: 40px; + background-color: white; + border-bottom: 1px solid #eee; } + +@media screen and (max-width: 768px) { + /*header 반응형*/ + body::-webkit-scrollbar { + display: none; } + + header { + position: fixed; + top: 0; + width: 100%; + height: 70px; + background-color: #444; + z-index: 99999; } + header > .inner { + position: relative; } + header > .inner > .toggle { + display: block; + position: absolute; + top: 0; + right: 0; + width: 70px; + height: 70px; + cursor: pointer; + text-indent: -99999px; + background-image: url(../images/toggle.png); } + header > .inner > .toggle.clse { + background-image: url(../images/toggle_cls.png); } + header > .inner > h1 { + position: absolute; + width: 200px; + height: 70px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-position: 20% 50%; + background-size: 50%; } + header > .inner > h1 > a { + display: block; + width: 100%; + height: 100%; } + header > .inner > .gnb { + display: none; + position: absolute; + top: 69px; + right: 0; + width: 100%; + background-color: #444; } + header > .inner > .gnb > ul > li { + float: inherit; + width: 100%; } + header > .inner > .gnb > ul > li > a { + display: block; + width: 100%; + height: 70px; + font-size: 15px; + font-weight: 600; + color: rgba(255, 255, 255, 0.6); + line-height: 70px; + padding-left: 30px; + text-align: left; } + header > .inner > .gnb > ul > li > a.on { + color: white; } + header > .inner > .gnb > ul > li > a:hover { + color: white; } + header > .inner > .gnb > ul > li > .sub { + position: inherit; + top: 0; + width: 100%; + background-color: #f1f1f1; + z-index: 5000; + display: none; } + header > .inner > .gnb > ul > li > .sub.sub01 { + position: inherit; + left: 0; } + header > .inner > .gnb > ul > li > .sub.sub01 > .subcontainer > ul { + margin-left: 0px; } + header > .inner > .gnb > ul > li > .sub.sub01 > .subcontainer > ul > li { + margin-left: 0px; + padding-left: 35px; } + header > .inner > .gnb > ul > li > .sub.sub02 { + position: inherit; + left: 0; } + header > .inner > .gnb > ul > li > .sub.sub02 > .subcontainer > ul > li { + margin-left: 0px; + padding-left: 35px; } + header > .inner > .gnb > ul > li > .sub.sub03 { + position: inherit; + left: 0; } + header > .inner > .gnb > ul > li > .sub.sub03 > .subcontainer > ul > li { + margin-left: 0px; } + header > .inner > .gnb > ul > li > .sub.sub04 { + position: inherit; + left: 0; } + header > .inner > .gnb > ul > li > .sub.sub04 > .subcontainer > ul { + margin-left: 0px; + padding-left: 35px; } + header > .inner > .gnb > ul > li > .sub.sub04 > .subcontainer > ul > li { + margin-left: 0px; } + header > .inner > .gnb > ul > li > .sub > .subcontainer > ul > li { + height: 60px; + line-height: 60px; + float: inherit; + font-size: 16px; + margin-left: 0px; + border-bottom: 1px solid #ccc; } + header > .inner > .gnb > ul > li > .sub > .subcontainer > ul > li:last-child { + border-bottom: none; } + header > .inner > .gnb > ul > li > .sub > .subcontainer > ul > li > a { + display: block; + font-weight: 600; + color: #333; } + header > .inner > .gnb > ul > li > .sub > .subcontainer > ul > li > a:hover { + color: #ffc700; } + header > .inner > .gnb .lang { + display: block; + position: absolute; + top: -60px; + right: 80px; + width: 60px; + height: 50px; + text-align: center; + line-height: 50px; + color: rgba(255, 255, 255, 0.7); + font-size: 13px; + font-weight: 600; + cursor: pointer; + border-radius: 14px; } + header > .inner > .gnb .lang:hover { + color: white; } + header > .inner > .gnb .lang > ul { + margin-top: 10px; + display: none; + width: 100%; + background-color: rgba(0, 0, 0, 0.5); } + header > .inner > .gnb .lang > ul > li { + line-height: 50px; } + header > .inner > .gnb .lang > ul > li:hover a { + color: #ffc700; } + header > .inner > .gnb .lang > ul > li.on a { + color: #ffc700; } + header > .inner > .gnb .lang > ul > li > a { + color: #fff; } + header > .sub_bg { + display: none; + position: absolute; + top: 70px; + width: 100%; + height: 40px; + background-color: white; + border-bottom: 1px solid #eee; } } +#mVisual { + position: relative; + overflow: hidden; + width: 100%; + height: 100vh; } + #mVisual > .mVisual_img { + width: 100%; + height: 100%; + z-index: -1; } + #mVisual > .mVisual_img > ul > li { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-indent: -99999px; + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; } + #mVisual > .mVisual_img > ul > li:nth-child(1) { + background-image: url(../images/img01.jpg); } + #mVisual > .mVisual_img > ul > li:nth-child(2) { + background-image: url(../images/mVisual02.jpg); + background-position: 50% 80%; } + #mVisual > .mVisual_img > ul > li:nth-child(3) { + background-image: url(../images/mVisual08.jpg); } + #mVisual > .mVisual_img > ul > li:nth-child(4) { + background-image: url(../images/mVisual04.jpg); } + #mVisual > .mVisual_txt { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 600px; + height: 200px; + background-color: rgba(0, 0, 0, 0.6); + transition: .5s; + z-index: 5000; } + #mVisual > .mVisual_txt > ul > li { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 100%; + transform: translate(-50%, -30%); + height: 100%; + text-align: center; } + #mVisual > .mVisual_txt > ul > li > dl > dt { + position: relative; + margin-bottom: 25px; + font-size: 35px; + font-weight: 600; + color: #fff; } + #mVisual > .mVisual_txt > ul > li > dl > dt:after { + position: absolute; + bottom: -15px; + left: 50%; + transform: translateX(-50%); + width: 120px; + height: 3px; + background-color: #ffc700; + content: ''; } + #mVisual > .mVisual_txt > ul > li > dl > dd { + letter-spacing: 2px; + line-height: 1.4em; + font-size: 16px; + color: #fff; } + #mVisual > .mVisual_indicator { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 600px; + height: 200px; + z-index: 6000; } + #mVisual > .mVisual_indicator:after { + position: absolute; + bottom: 24px; + right: 54px; + width: 6px; + height: 6px; + background-color: #ffc700; + border-radius: 5px; + content: ''; } + #mVisual > .mVisual_indicator > p { + display: block; + position: absolute; + bottom: 20px; + width: 17px; + height: 15px; + text-indent: -99999px; + transition: .4s; + cursor: pointer; + background-repeat: no-repeat; + background-size: cover; } + #mVisual > .mVisual_indicator > p.mVisual_prev_btn { + background-image: url(../images/prev_btn.png); + right: 80px; } + #mVisual > .mVisual_indicator > p.mVisual_prev_btn:hover { + background-image: url(../images/prev_btn_hover.png); } + #mVisual > .mVisual_indicator > p.mVisual_next_btn { + background-image: url(../images/next_btn.png); + right: 20px; } + #mVisual > .mVisual_indicator > p.mVisual_next_btn:hover { + background-image: url(../images/next_btn_hover.png); } + #mVisual > .downArrow { + position: absolute; + bottom: 20px; + left: 50%; + transform: translateX(-50%) rotate(90deg); + width: 50px; + height: 50px; + cursor: pointer; + background-image: url(../images/next_btn.png); + background-repeat: no-repeat; + background-position: 50% 50%; + animation: downArrow 0.9s infinite; } + +@media screen and (max-width: 768px) { + /*mVisual 반응형*/ + #mVisual { + position: relative; + overflow: hidden; + width: 100%; + height: 100vh; } + #mVisual > .mVisual_img { + width: 100%; + height: 100%; + z-index: -1; } + #mVisual > .mVisual_img > ul > li { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-indent: -99999px; + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; } + #mVisual > .mVisual_img > ul > li:nth-child(1) { + background-image: url(../images/img01.jpg); } + #mVisual > .mVisual_img > ul > li:nth-child(2) { + background-image: url(../images/mVisual02.jpg); + background-position: 50% 80%; } + #mVisual > .mVisual_img > ul > li:nth-child(3) { + background-image: url(../images/mVisual08.jpg); } + #mVisual > .mVisual_img > ul > li:nth-child(4) { + background-image: url(../images/mVisual04.jpg); } + #mVisual > .mVisual_txt { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%; + height: 200px; + background-color: rgba(0, 0, 0, 0.6); + transition: .5s; + z-index: 5000; } + #mVisual > .mVisual_txt > ul > li { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 100%; + transform: translate(-50%, -30%); + height: 100%; + text-align: center; } + #mVisual > .mVisual_txt > ul > li > dl > dt { + position: relative; + margin-bottom: 25px; + font-size: 35px; + font-weight: 600; + color: #fff; } + #mVisual > .mVisual_txt > ul > li > dl > dt:after { + position: absolute; + bottom: -15px; + left: 50%; + transform: translateX(-50%); + width: 120px; + height: 3px; + background-color: #ffc700; + content: ''; } + #mVisual > .mVisual_txt > ul > li > dl > dd { + letter-spacing: 2px; + line-height: 1.4em; + font-size: 16px; + color: #fff; } + #mVisual > .mVisual_indicator { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 600px; + height: 200px; + z-index: 6000; } + #mVisual > .mVisual_indicator:after { + position: absolute; + bottom: 28px; + left: 50%; + transform: translateX(-50%); + width: 6px; + height: 6px; + background-color: #ffc700; + border-radius: 5px; + content: ''; } + #mVisual > .mVisual_indicator > p { + display: block; + position: absolute; + bottom: 20px; + width: 100px; + height: 23px; + text-indent: -99999px; + transition: .4s; + cursor: pointer; + background-repeat: no-repeat; + background-size: contain; } + #mVisual > .mVisual_indicator > p.mVisual_prev_btn { + background-image: url(../images/prev_btn.png); + background-position: 100% 50%; + left: 30%; } + #mVisual > .mVisual_indicator > p.mVisual_prev_btn:hover { + background-image: url(../images/prev_btn_hover.png); } + #mVisual > .mVisual_indicator > p.mVisual_next_btn { + background-image: url(../images/next_btn.png); + left: 53%; } + #mVisual > .mVisual_indicator > p.mVisual_next_btn:hover { + background-image: url(../images/next_btn_hover.png); } + #mVisual > .downArrow { + position: absolute; + bottom: 20px; + left: 50%; + transform: translateX(-50%) rotate(90deg); + width: 50px; + height: 50px; + cursor: pointer; + background-image: url(../images/next_btn.png); + background-repeat: no-repeat; + background-position: 50% 50%; + animation: downArrow 0.9s infinite; } } +#company { + position: relative; + width: 100%; } + #company > .inner { + /* >.company_info { + //float: left; + width: 600px; + height: 500px; + margin-top: 45px; + //background-color: red; + + >ul { + margin : 50px 0 0 10px; + >li { + margin-top : 20px; + font-size: 20px; + font-weight: 600; + letter-spacing: 0px; + color: #333; + + >em { + color: #fc4040; + }//end of em + + &:nth-child(5) { + line-height: 1.5em; + }//end of li:nth-child(5) + + >dl { + >dt { + margin-top: 40px; + font-size: 25px; + color: #aaa; + }//end of dt + >dd { + margin-top: 10px; + font-size: 14px; + font-weight: 500; + color: #bbb; + letter-spacing: 0px; + line-height: 1.7em; + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of company_info + + */ } + #company > .inner > h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #222; + text-transform: uppercase; } + #company > .inner > h3:after { + position: absolute; + bottom: -20px; + left: 50%; + transform: translateX(-50%); + font-size: 13px; + font-weight: 800; + color: #263d78; + letter-spacing: -0.5px; + content: "company Status"; } + #company > .inner > .company_img { + width: 100%; + height: 450px; + margin: 45px 0 50px; + background-image: url(../images/intro.png); + background-position: 45% 50%; + background-size: contain; + background-repeat: no-repeat; } + #company > .inner > .company_intro { + margin: 50px 0 50px; + text-align: left; + font-size: 16px; + font-weight: 500; + line-height: 1.9em; } + #company > .inner > .company_intro > .company_l { + position: relative; + float: left; + width: 600px; + margin-top: -10px; + text-align: right; } + #company > .inner > .company_intro > .company_l:after { + position: absolute; + top: 10px; + right: 0; + width: 2px; + height: 222px; + background-color: #e5e5e5; + content: ''; } + #company > .inner > .company_intro > .company_l > ul { + padding-right: 30px; } + #company > .inner > .company_intro > .company_l > ul > li > dl > dt { + font-size: 20px; + margin-bottom: 7px; + color: #6c6c6c; } + #company > .inner > .company_intro > .company_l > ul > li > dl > dd { + font-size: 30px; + font-weight: 900; + color: #263d78; } + #company > .inner > .company_intro > .company_l > ol { + font-size: 22px; + margin-top: 40px; + padding-right: 30px; + font-weight: 600; } + #company > .inner > .company_intro > .company_l > ol > li { + line-height: 2em; } + #company > .inner > .company_intro > .company_l > ol > li > dl > dd > em { + color: #eeba01; } + #company > .inner > .company_intro > .company_r { + float: left; + width: 600px; + text-align: left; } + #company > .inner > .company_intro > .company_r > ul { + padding-left: 30px; + height: 260px; } + #company > .inner > .company_intro > .company_r > ul > li { + margin-bottom: 5px; + width: 200px; + background-color: #263d78; + transition: .2s; + height: 40px; } + #company > .inner > .company_intro > .company_r > ul > li > a { + display: block; + padding-left: 15px; + font-weight: 500; + font-size: 15px; + letter-spacing: px; + line-height: 38px; + height: 42px; + color: #fff; + transition: .2s; } + #company > .inner > .company_intro > .company_r > ul > li:hover { + background-color: #ffc700; } + #company > .inner > .company_intro > .company_r > ul > li:hover a { + color: #f1f1f1; } + +@media screen and (max-width: 768px) { + /*company 반응형*/ + #company { + position: relative; + width: 100%; } + #company > .inner > h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #222; + text-transform: uppercase; } + #company > .inner > h3:after { + position: absolute; + bottom: -20px; + left: 50%; + transform: translateX(-50%); + font-size: 13px; + font-weight: 800; + color: #263d78; + letter-spacing: -0.5px; + content: "company Status"; } + #company > .inner > .company_img { + display: none; + width: 100%; + height: 450px; + margin: 45px 0 50px; + background-image: url(../images/intro.png); + background-position: 45% 50%; + background-size: contain; + background-repeat: no-repeat; } + #company > .inner > .company_intro { + width: 100%; + margin: 50px 0 50px; + text-align: center; + font-size: 16px; + font-weight: 500; + line-height: 1.9em; } + #company > .inner > .company_intro > .company_l { + position: relative; + float: inherit; + width: 100%; + margin-top: 0px; + padding-top: 30px; + text-align: center; } + #company > .inner > .company_intro > .company_l:after { + display: none; + position: absolute; + top: 10px; + right: 0; + width: 2px; + height: 222px; + background-color: #e5e5e5; + content: ''; } + #company > .inner > .company_intro > .company_l > ul { + padding-right: 0px; } + #company > .inner > .company_intro > .company_l > ul > li > dl > dt { + font-size: 20px; + margin-bottom: 7px; + color: #6c6c6c; } + #company > .inner > .company_intro > .company_l > ul > li > dl > dd { + font-size: 30px; + font-weight: 900; + color: #263d78; } + #company > .inner > .company_intro > .company_l > ol { + font-size: 16px; + margin-top: 20px; + padding: 0 5px; + font-weight: 500; } + #company > .inner > .company_intro > .company_l > ol > li { + line-height: 1.45em; } + #company > .inner > .company_intro > .company_l > ol > li > dl > dd > em { + color: #eeba01; } + #company > .inner > .company_intro > .company_r { + float: inherit; + width: 100%; + padding-top: 40px; + text-align: center; } + #company > .inner > .company_intro > .company_r > ul { + padding-left: 0px; + height: auto; } + #company > .inner > .company_intro > .company_r > ul > li { + margin: 0 auto 5px; + width: 90%; + background-color: #263d78; + transition: .2s; + height: 50px; } + #company > .inner > .company_intro > .company_r > ul > li > a { + display: block; + padding-left: 15px; + font-weight: 500; + font-size: 17px; + letter-spacing: 1px; + line-height: 50px; + height: 50px; + color: #fff; + transition: .2s; } + #company > .inner > .company_intro > .company_r > ul > li:hover { + background-color: #ffc700; } + #company > .inner > .company_intro > .company_r > ul > li:hover a { + color: #f1f1f1; } } +#service { + margin-top: 20px; + width: 100%; + height: 600px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 70%; } + #service > .inner { + position: relative; + /*indicator position*/ } + #service > .inner > h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #333; + text-transform: uppercase; } + #service > .inner > h3:after { + position: absolute; + bottom: -20px; + left: 50%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #263d78; + letter-spacing: 0px; + content: "BUSINESS AREA"; } + #service > .inner > .service_box { + position: relative; + /*service_container position*/ + overflow: hidden; + width: 1200px; + height: 402px; + margin: 50px auto 0; } + #service > .inner > .service_box > .service_container { + position: absolute; + top: 1px; + left: 0; + width: 5000px; } + #service > .inner > .service_box > .service_container > div { + float: left; + width: 1200px; + height: 100%; } + #service > .inner > .service_box > .service_container > div > ul { + width: 1200px; + margin: 0 auto; } + #service > .inner > .service_box > .service_container > div > ul > li { + position: relative; + float: left; + margin-left: 20px; + width: 275px; + height: 370px; + transition: .5s; + background-color: #fff; + border-radius: 5px; } + #service > .inner > .service_box > .service_container > div > ul > li:after { + opacity: 0; + position: absolute; + top: 2.5px; + left: 5px; + width: 260px; + height: 360px; + border: 2px solid #263d78; + transition: .3s; + content: ''; } + #service > .inner > .service_box > .service_container > div > ul > li:hover:after { + opacity: 1; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > dt { + margin: 50px auto 0px; + width: 120px; + height: 120px; + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + transition: .4s; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > dt > p { + display: block; + text-indent: -99999px; + margin: 0px auto; + padding-top: 40px; + width: 90px; + height: 90px; + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + transition: .6s; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .topic { + margin: 0px 0; + width: 100%; + height: 33px; + font-size: 18px; + font-weight: 700; + text-align: center; + line-height: 30px; + transition: .6s; + color: #222; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .info { + width: 100%; + min-height: 100px; + line-height: 1.6em; + letter-spacing: -1px; + font-size: 13px; + font-weight: 500; + text-align: center; + transition: .6s; + color: #aaa; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .more { + display: block; + width: 150px; + margin: 5px auto 0; + text-align: center; + font-weight: 600; + color: #ffc700; + z-index: 4000; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .more > em { + color: #263d78; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .more > a { + position: absolute; + top: 0; + left: 0; + display: block; + width: 275px; + height: 370px; + color: #fff; + z-index: 7000; } + #service > .inner > .service_box > .service_container > .service_1 > ul > li:nth-child(1) p { + background-image: url(../images/icon_4.png); } + #service > .inner > .service_box > .service_container > .service_1 > ul > li:nth-child(2) p { + background-image: url(../images/icon_2.png); } + #service > .inner > .service_box > .service_container > .service_1 > ul > li:nth-child(3) p { + background-image: url(../images/icon_1.png); } + #service > .inner > .service_box > .service_container > .service_1 > ul > li:nth-child(4) p { + background-image: url(../images/icon_7.png); } + #service > .inner > .service_box > .service_container > .service_2 { + display: none; } + #service > .inner > .service_box > .service_container > .service_2 > ul > li { + background-size: 20%; } + #service > .inner > .service_indicator { + position: absolute; + bottom: -35px; + left: 50%; + transform: translateX(-50%); + width: 100px; + height: 20px; } + #service > .inner > .service_indicator > ul > li { + float: left; + margin-left: 20px; + width: 20px; + height: 20px; + background-color: #333; + border-radius: 20px; + cursor: pointer; } + #service > .inner > .service_indicator > ul > li.on { + background-color: #fff; } + #service > .inner > .service_RL_btn { + display: none; + position: absolute; + top: 50%; + width: 100%; } + #service > .inner > .service_RL_btn > p { + position: absolute; + top: 0; + width: 40px; + height: 40px; + text-indent: -99999px; + cursor: pointer; } + #service > .inner > .service_RL_btn > .prev { + position: absolute; + left: -20px; } + #service > .inner > .service_RL_btn > .prev:after { + position: absolute; + top: 25%; + left: -10px; + transform: rotate(-45deg); + width: 25px; + height: 2px; + background-color: #263d78; + content: ''; } + #service > .inner > .service_RL_btn > .prev:before { + position: absolute; + bottom: 25%; + left: -10px; + transform: rotate(45deg); + width: 25px; + height: 2px; + background-color: #263d78; + content: ''; } + #service > .inner > .service_RL_btn > .next { + position: absolute; + right: -20px; } + #service > .inner > .service_RL_btn > .next:after { + position: absolute; + top: 25%; + left: 25px; + transform: rotate(45deg); + width: 25px; + height: 2px; + background-color: #263d78; + content: ''; } + #service > .inner > .service_RL_btn > .next:before { + position: absolute; + bottom: 25%; + left: 25px; + transform: rotate(-45deg); + width: 25px; + height: 2px; + background-color: #263d78; + content: ''; } + +@media screen and (max-width: 768px) { + /*service 768px 반응형*/ + #service { + margin-top: 20px; + width: 100%; + height: auto; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 70%; } + #service > .inner { + position: relative; + /*indicator position*/ } + #service > .inner > h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #333; + text-transform: uppercase; } + #service > .inner > h3:after { + position: absolute; + bottom: -20px; + left: 50%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #263d78; + letter-spacing: 0px; + content: "BUSINESS AREA"; } + #service > .inner > .service_box { + position: relative; + /*service_container position*/ + overflow: hidden; + width: 350px; + height: 402px; + margin: 50px auto; } + #service > .inner > .service_box > .service_container { + position: absolute; + top: 1px; + left: 0; + width: 1400px; } + #service > .inner > .service_box > .service_container > div { + float: left; + width: 1400px; + height: 100%; } + #service > .inner > .service_box > .service_container > div > ul { + width: 1400px; + margin: 0 auto; } + #service > .inner > .service_box > .service_container > div > ul > li { + position: relative; + float: left; + margin-left: 0px; + width: 350px; + height: 370px; + transition: .5s; + background-color: #fff; + border-radius: 5px; } + #service > .inner > .service_box > .service_container > div > ul > li:after { + opacity: 0; + position: absolute; + top: 10px; + left: 10px; + width: 325px; + height: 345px; + border: 2px solid #263d78; + transition: .3s; + content: ''; } + #service > .inner > .service_box > .service_container > div > ul > li:hover:after { + opacity: 1; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > dt { + margin: 50px auto 0px; + width: 120px; + height: 120px; + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + transition: .4s; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > dt > p { + display: block; + text-indent: -99999px; + margin: 0px auto; + padding-top: 40px; + width: 90px; + height: 90px; + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + transition: .6s; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .topic { + margin: 0px 0; + width: 100%; + height: 33px; + font-size: 23px; + font-weight: 700; + text-align: center; + line-height: 30px; + transition: .6s; + color: #222; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .info { + width: 100%; + min-height: 100px; + line-height: 1.6em; + letter-spacing: -1px; + font-size: 15px; + font-weight: 500; + text-align: center; + transition: .6s; + color: #aaa; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .more { + display: block; + width: 150px; + margin: 5px auto 0; + text-align: center; + font-weight: 600; + color: #ffc700; + z-index: 4000; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .more > em { + color: #263d78; } + #service > .inner > .service_box > .service_container > div > ul > li > dl > .more > a { + position: absolute; + top: 0; + left: 0; + display: block; + width: 100%; + height: 370px; + color: #fff; + z-index: 7000; } + #service > .inner > .service_box > .service_container > .service_1 > ul > li:nth-child(1) p { + background-image: url(../images/icon_4.png); } + #service > .inner > .service_box > .service_container > .service_1 > ul > li:nth-child(2) p { + background-image: url(../images/icon_2.png); } + #service > .inner > .service_box > .service_container > .service_1 > ul > li:nth-child(3) p { + background-image: url(../images/icon_1.png); } + #service > .inner > .service_box > .service_container > .service_1 > ul > li:nth-child(4) p { + background-image: url(../images/icon_7.png); } + #service > .inner > .service_box > .service_container > .service_2 { + display: none; } + #service > .inner > .service_box > .service_container > .service_2 > ul > li { + background-size: 20%; } + #service > .inner > .service_RL_btn { + display: block; + position: absolute; + top: 50%; + width: 100%; } + #service > .inner > .service_RL_btn > p { + position: absolute; + top: -35px; + width: 60px; + height: 60px; + text-indent: -99999px; + z-index: 7000; + cursor: pointer; } + #service > .inner > .service_RL_btn > .prev { + position: absolute; + left: 60px; } + #service > .inner > .service_RL_btn > .prev:after { + position: absolute; + top: 35%; + left: 20px; + transform: rotate(-45deg); + width: 25px; + height: 2px; + background-color: #263d78; + content: ''; } + #service > .inner > .service_RL_btn > .prev:before { + position: absolute; + bottom: 35%; + left: 20px; + transform: rotate(45deg); + width: 25px; + height: 2px; + background-color: #263d78; + content: ''; } + #service > .inner > .service_RL_btn > .next { + position: absolute; + right: 60px; } + #service > .inner > .service_RL_btn > .next:after { + position: absolute; + top: 35%; + left: 15px; + transform: rotate(45deg); + width: 25px; + height: 2px; + background-color: #263d78; + content: ''; } + #service > .inner > .service_RL_btn > .next:before { + position: absolute; + bottom: 35%; + left: 15px; + transform: rotate(-45deg); + width: 25px; + height: 2px; + background-color: #263d78; + content: ''; } } +#company_m_info { + width: 100%; + height: 240px; + background-image: url(../images/bg_1.jpg); + background-attachment: fixed; + background-repeat: no-repeat; + background-position: 90% 50%; + background-size: cover; } + #company_m_info > .inner { + padding-top: 90px; } + #company_m_info > .inner > ul { + width: 100%; + height: 100px; } + #company_m_info > .inner > ul > li { + width: 300px; + float: left; + text-align: center; + color: #fff; + font-size: 20px; } + #company_m_info > .inner > ul > li:nth-child(1) { + margin-left: 150px; } + #company_m_info > .inner > ul > li:nth-child(2) { + position: relative; } + #company_m_info > .inner > ul > li:nth-child(2):after { + position: absolute; + top: 50%; + left: 0; + width: 1px; + height: 15px; + background-color: #888; + content: ''; } + #company_m_info > .inner > ul > li:nth-child(2):before { + position: absolute; + top: 50%; + right: 0; + width: 1px; + height: 15px; + background-color: #888; + content: ''; } + #company_m_info > .inner > ul > li:nth-child(2) > dl > dt { + letter-spacing: -3px; } + #company_m_info > .inner > ul > li > dl > dt { + font-size: 40px; + font-weight: 500; + color: #ffc700; + margin-bottom: 10px; } + #company_m_info > .inner > ul > li > dl > dt > span { + font-size: 17px; } + #company_m_info > .inner > ul > li > dl > dd { + font-size: 17px; } + +@media screen and (max-width: 768px) { + /*company m info 768px 반응형*/ + #company_m_info { + display: none; + width: 100%; + height: 240px; + background-image: url(../images/bg_1.jpg); + background-attachment: fixed; + background-repeat: no-repeat; + background-position: 90% 50%; + background-size: cover; } + #company_m_info > .inner { + padding-top: 90px; } + #company_m_info > .inner > ul { + width: 100%; + height: 100px; } + #company_m_info > .inner > ul > li { + width: 300px; + float: left; + text-align: center; + color: #fff; + font-size: 20px; } + #company_m_info > .inner > ul > li:nth-child(1) { + margin-left: 150px; } + #company_m_info > .inner > ul > li:nth-child(2) { + position: relative; } + #company_m_info > .inner > ul > li:nth-child(2):after { + position: absolute; + top: 50%; + left: 0; + width: 1px; + height: 15px; + background-color: #888; + content: ''; } + #company_m_info > .inner > ul > li:nth-child(2):before { + position: absolute; + top: 50%; + right: 0; + width: 1px; + height: 15px; + background-color: #888; + content: ''; } + #company_m_info > .inner > ul > li:nth-child(2) > dl > dt { + letter-spacing: -3px; } + #company_m_info > .inner > ul > li > dl > dt { + font-size: 40px; + font-weight: 500; + color: #ffc700; + margin-bottom: 10px; } + #company_m_info > .inner > ul > li > dl > dt > span { + font-size: 17px; } + #company_m_info > .inner > ul > li > dl > dd { + font-size: 17px; } } +#contact { + width: 100%; + height: 750px; + background-color: #263d78; } + #contact > h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #fff; + text-transform: uppercase; } + #contact > h3:after { + position: absolute; + bottom: -20px; + left: 50.2%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #111; + letter-spacing: 4px; + content: "How to come"; } + #contact > .mapContainer { + width: 600px; + height: 300px; + margin: 60px auto 200px; } + #contact > .mapContainer > .map { + width: 600px; + height: 450px; + background-image: url(../images/map_18.08.06.jpg); + background-position: 50% 50%; + background-size: cover; + border: 0; } + #contact > .mapContainer > .map > a { + display: block; + width: 100%; + height: 100%; + text-indent: -99999px; } + #contact > .mapInfo { + position: relative; + width: 100%; + text-align: center; } + #contact > .mapInfo:after { + position: absolute; + top: 0; + left: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: 0 50%; + content: ''; } + #contact > .mapInfo:before { + position: absolute; + bottom: 0; + right: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: -35px 50%; + content: ''; } + #contact > .mapInfo > .inner > ul > li { + font-size: 18px; + font-weight: 600; + color: #fff; + line-height: 1.8em; } + #contact > .mapInfo > .inner > ul > li > span { + color: #111; + font-weight: 900; } + +@media screen and (max-width: 768px) { + /*contact 768px 반응형*/ + #contact { + width: 100%; + height: auto; + background-color: #263d78; } + #contact > h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #fff; + text-transform: uppercase; } + #contact > h3:after { + position: absolute; + bottom: -20px; + left: 50.2%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #111; + letter-spacing: 4px; + content: "How to come"; } + #contact > .mapContainer { + width: 90%; + height: 480px; + margin: 60px auto 40px; } + #contact > .mapContainer > .map { + width: 100%; + height: 450px; + background-image: url(../images/map_18.08.06.jpg); + background-position: 10% 50%; + background-size: cover; + border: 0; } + #contact > .mapContainer > .map > a { + display: block; + width: 100%; + height: 100%; + text-indent: -99999px; } + #contact > .mapInfo { + position: relative; + width: 100%; + text-align: center; + padding-bottom: 50px; } + #contact > .mapInfo:after { + display: none; + position: absolute; + top: 0; + left: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: 0 50%; + content: ''; } + #contact > .mapInfo:before { + display: none; + position: absolute; + bottom: 0; + right: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: -35px 50%; + content: ''; } + #contact > .mapInfo > .inner > ul > li { + font-size: 18px; + font-weight: 600; + color: #fff; + line-height: 1.8em; } + #contact > .mapInfo > .inner > ul > li > span { + display: block; + color: #111; + font-weight: 900; } } +footer { + width: 100%; + height: 170px; + background-color: #333; } + footer > .inner { + position: relative; + padding-top: 20px; } + footer > .inner > h1 { + float: left; + margin-left: 40px; + width: 120px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; } + footer > .inner > .f_left { + float: left; + margin-left: 50px; } + footer > .inner > .f_left > ul { + width: 280px; } + footer > .inner > .f_left > ul > li { + width: 320px; + text-align: center; } + footer > .inner > .f_left > ul > li:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); } + footer > .inner > .f_left > ul > li:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); } + footer > .inner > .f_left > ul > li:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); } + footer > .inner > .f_left > ul > li > dl > dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + footer > .inner > .f_left > ul > li > dl > dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > .f_left > ul > li > dl > dd > em { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a:hover { + text-decoration: underline; } + footer > .inner > address { + float: left; + margin-top: 0px; + margin-left: 30px; + width: 340px; } + footer > .inner > address > ul { + width: 350px; } + footer > .inner > address > ul > li { + width: 320px; + text-align: center; } + footer > .inner > address > ul > li:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); } + footer > .inner > address > ul > li:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); } + footer > .inner > address > ul > li:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); } + footer > .inner > address > ul > li > dl > dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + footer > .inner > address > ul > li > dl > dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > address > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > address > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a:hover { + text-decoration: underline; } + footer > .inner > .f_nav { + float: right; + margin-top: 0px; + width: 180px; } + footer > .inner > .f_nav > ul > li { + float: left; + margin-right: 9px; + padding-right: 11px; + background-image: url(../images/f_right.png); + background-repeat: no-repeat; + background-position: 100% 73%; } + footer > .inner > .f_nav > ul > li:last-child { + margin-right: none; + background-image: none; } + footer > .inner > .f_nav > ul > li > a { + font-size: 13px; + color: #fff; } + footer > .inner > .copyright { + position: absolute; + top: 120px; + right: -140px; + transform: translateX(-50%); + width: 315px; + font-size: 13px; + letter-spacing: 1px; + color: #fff; } + footer > .inner:after { + position: absolute; + top: 30px; + left: 200px; + transform: translateX(-50%); + width: 1px; + height: 120px; + background-color: #808080; + content: ''; } + +@media screen and (max-width: 768px) { + /*footer 768px 반응형*/ + footer { + width: 100%; + height: auto; + background-color: #333; } + footer > .inner { + position: relative; + padding-top: 20px; } + footer > .inner > h1 { + float: inherit; + margin: 0 auto 180px; + width: 120px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; } + footer > .inner > .f_left { + float: inherit; + margin: 0 auto; + width: 100%; } + footer > .inner > .f_left > ul { + width: 100%; } + footer > .inner > .f_left > ul > li { + width: 100%; } + footer > .inner > .f_left > ul > li > dl > dt { + display: none; + margin: 0 auto; + width: 100%; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + footer > .inner > .f_left > ul > li > dl > dd { + padding-left: 20px; + text-align: left; + margin-top: 8px; + font-size: 16px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > .f_left > ul > li > dl > dd > em { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a:hover { + text-decoration: none; } + footer > .inner > address { + border-top: 1px solid #666; + float: inherit; + margin: 10px auto; + width: 100%; } + footer > .inner > address > ul { + width: 100%; } + footer > .inner > address > ul > li { + width: 100%; + text-align: center; } + footer > .inner > address > ul > li:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); } + footer > .inner > address > ul > li:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); } + footer > .inner > address > ul > li:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); } + footer > .inner > address > ul > li > dl > dt { + display: none; } + footer > .inner > address > ul > li > dl > dd { + padding-left: 20px; + text-align: left; + margin-top: 6px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > address > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > address > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a:hover { + text-decoration: underline; } + footer > .inner > .f_nav { + position: absolute; + top: 75px; + float: inherit; + margin-top: 0px; + width: 100%; } + footer > .inner > .f_nav > ul > li { + width: 100%; + text-align: center; + float: inherit; + margin-right: 0px; + padding-right: 0px; + background-image: none; + background-repeat: no-repeat; + background-position: 100% 73%; + border-top: 1px solid #666; } + footer > .inner > .f_nav > ul > li:last-child { + margin-right: none; + background-image: none; + border-bottom: 1px solid #666; } + footer > .inner > .f_nav > ul > li > a { + display: block; + height: 50px; + line-height: 50px; + font-size: 16px; + color: #fff; } + footer > .inner > .copyright { + border-top: 1px solid #666; + position: static; + padding: 20px 0; + top: 10px; + right: 50%; + transform: translateX(0); + width: 100%; + font-size: 13px; + letter-spacing: 1px; + text-align: center; + color: #fff; } + footer > .inner:after { + display: none; } } +@keyframes downArrow { + 0% { + bottom: 40px; } + 100% { + bottom: 20px; } } + +/*# sourceMappingURL=common.css.map */ diff --git a/eng/css/common.css.map b/eng/css/common.css.map new file mode 100644 index 0000000..8078a35 --- /dev/null +++ b/eng/css/common.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": ";AAGA,SAAU;EACP,KAAK,EAAG,CAAC;EAET,eAAQ;IACL,OAAO,EAAE,KAAK;IACd,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,EAAE;;AAIjB,QAAS;EACN,QAAQ,EAAE,QAAQ;EAClB,IAAI,EAAE,QAAQ;;AAGjB,MAAO;EACJ,KAAK,EAAE,MAAM;EACb,MAAM,EAAE,MAAM;;AAGjB,oCAAsC;EAClC,MAAO;IACJ,KAAK,EAAE,IAAI;AAMlB,KAAM;EACH,KAAK,EAAE,IAAI;EACX,gBAAgB,EAAE,OAAO;;AAI5B,QAAS;EACN,OAAO,EAAE,IAAI;EACb,QAAQ,EAAE,KAAK;EACf,MAAM,EAAG,IAAI;EACb,KAAK,EAAG,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,gBAAgB,EA5CJ,OAAO;EA6CnB,aAAa,EAAE,IAAI;EACnB,MAAM,EAAE,OAAO;EACf,OAAO,EAAE,IAAI;EAEb,cAAQ;IACL,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,GAAG;IACR,IAAI,EAAE,GAAG;IACT,SAAS,EAAE,gBAAgB;IAC3B,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,2BAA2B;IAC7C,mBAAmB,EAAE,OAAO;IAC5B,OAAO,EAAE,EAAE;;AAMjB,IAAK;EACF,UAAU,EAAE,MAAM;;AAGrB,EAAG;EACE,SAAS,EAAE,IAAI;;AAOpB,mBAAoB;EACjB,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,GAAG;EACX,MAAM,EAAE,cAAc;;AAEzB;uCACwC;EACrC,OAAO,EAAE,KAAK;EACd,MAAM,EAAE,IAAI;EACZ,UAAU,EAAE,8BAA8B;;AAE7C,yBAA0B;EAAC,UAAU,EAAE,OAAO;EAC3C,qBAAqB,EAAE,IAAI;EAC3B,aAAa,EAAC,IAAI;EAClB,kBAAkB,EAAE,gCAA4B;;AAEnD,yBAA0B;EACvB,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,IAAI;EACX,UAAU,EAAE,kBAAc;EAC1B,qBAAqB,EAAE,GAAG;EAC1B,aAAa,EAAE,GAAG;EAClB,kBAAkB,EAAE,gCAA4B;;AAInD,oCAAoC;AAGpC,MAAO;EACJ,QAAQ,EAAE,KAAK;EACf,GAAG,EAAE,CAAC;EACN,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,IAAI;EACZ,gBAAgB,EAAE,kBAAqB;EAEvC,OAAO,EAAE,KAAK;EACd,UAAU,EAAE,GAAG;EAEf,eAAQ;IACL,QAAQ,EAAE,QAAQ;IAGlB,yBAAS;MACL,OAAO,EAAE,IAAI;MACb,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,CAAC;MACN,KAAK,EAAE,CAAC;MACR,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,MAAM,EAAE,OAAO;MACf,WAAW,EAAE,QAAQ;MACrB,gBAAgB,EAAE,yBAAyB;IAG/C,oBAAI;MACD,QAAQ,EAAE,QAAQ;MAClB,KAAK,EAAE,KAAK;MACZ,MAAM,EAAE,IAAI;MACZ,WAAW,EAAE,QAAQ;MACrB,gBAAgB,EAAE,uBAAuB;MACzC,iBAAiB,EAAE,SAAS;MAC5B,mBAAmB,EAAE,OAAO;MAC5B,eAAe,EAAE,GAAG;MAGpB,wBAAG;QACA,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;IAKlB,sBAAM;MACH,QAAQ,EAAE,QAAQ;MAClB,KAAK,EAAE,CAAC;MACR,KAAK,EAAE,KAAK;MAIT,gCAAI;QACD,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,KAAK;QAIZ,oCAAG;UACA,OAAO,EAAE,KAAK;UACd,MAAM,EAAE,IAAI;UACZ,SAAS,EAAE,IAAI;UACf,WAAW,EAAE,GAAG;UAChB,KAAK,EAAE,wBAAqB;UAC5B,WAAW,EAAE,IAAI;UACjB,UAAU,EAAE,MAAM;UAElB,uCAAK;YACD,KAAK,EAAE,KAAmB;UAG9B,0CAAQ;YACJ,KAAK,EAAE,KAAmB;QASjC,uCAAM;UACF,QAAQ,EAAE,QAAQ;UAClB,MAAM,EAAE,KAAK;UACb,KAAK,EAAE,IAAI;UAEX,OAAO,EAAE,IAAI;UACb,OAAO,EAAE,IAAI;UAEb,6CAAQ;YAEJ,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,CAAC;YAGP,kEAAmB;cACf,WAAW,EAAE,IAAI;cAChB,uEAAK;gBACF,WAAW,EAAE,IAAI;UAK7B,6CAAQ;YAEJ,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,CAAC;YAGP,uEAAwB;cACpB,WAAW,EAAE,IAAI;UAGzB,6CAAQ;YAEJ,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,CAAC;YAGP,uEAAwB;cACpB,WAAW,EAAE,IAAI;UAGzB,6CAAQ;YAEJ,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,CAAC;YAGP,kEAAmB;cACf,WAAW,EAAE,KAAK;cAElB,uEAAK;gBACD,WAAW,EAAE,IAAI;UASzB,iEAAQ;YACJ,MAAM,EAAE,IAAI;YACZ,WAAW,EAAE,IAAI;YACjB,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,IAAI;YAEjB,qEAAG;cACC,OAAO,EAAE,KAAK;cACd,WAAW,EAAE,GAAG;cAChB,KAAK,EAAE,IAAI;cAEX,2EAAQ;gBACL,KAAK,EAnQvB,OAAO;MA+Qd,4BAAM;QACF,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,CAAC;QACN,KAAK,EAAE,GAAG;QACV,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE,IAAI;QACjB,KAAK,EAAE,wBAAqB;QAC5B,WAAW,EAAE,GAAG;QAChB,MAAM,EAAE,OAAO;QAGhB,kCAAQ;UAAE,KAAK,EAAE,KAAmB;QAEpC,iCAAI;UACA,OAAO,EAAE,IAAI;UACb,KAAK,EAAE,IAAI;UACX,gBAAgB,EAAE,kBAAqB;UAEvC,sCAAI;YACA,WAAW,EAAE,IAAI;YAEjB,8CAAU;cACN,KAAK,EAvSb,OAAO;YAySH,2CAAO;cACH,KAAK,EA1Sb,OAAO;YA4SH,0CAAG;cACC,KAAK,EAAE,IAAI;EAQhC,gBAAS;IACL,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,IAAI;IACT,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,KAAsB;IACxC,aAAa,EAAE,cAAc;;AAOpC,oCAAsC;EAAC,cAAc;EACjD,uBAAwB;IAAC,OAAO,EAAE,IAAI;;EAEtC,MAAO;IACJ,QAAQ,EAAE,KAAK;IACf,GAAG,EAAE,CAAC;IACN,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,IAAI;IAEtB,OAAO,EAAE,KAAK;IAGd,eAAQ;MACL,QAAQ,EAAE,QAAQ;MAGlB,yBAAS;QACL,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,CAAC;QACN,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,OAAO;QACf,WAAW,EAAE,QAAQ;QACrB,gBAAgB,EAAE,yBAAyB;QAE3C,8BAAO;UACH,gBAAgB,EAAE,6BAA6B;MAMvD,oBAAI;QACD,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,QAAQ;QACrB,gBAAgB,EAAE,uBAAuB;QACzC,iBAAiB,EAAE,SAAS;QAC5B,mBAAmB,EAAE,OAAO;QAC5B,eAAe,EAAE,GAAG;QAGpB,wBAAG;UACA,OAAO,EAAE,KAAK;UACd,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,IAAI;MAKlB,sBAAM;QACH,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAG,IAAI;QACV,KAAK,EAAE,CAAC;QACR,KAAK,EAAE,IAAI;QACX,gBAAgB,EAAE,IAAI;QAInB,gCAAI;UACD,KAAK,EAAE,OAAO;UACd,KAAK,EAAE,IAAI;UAIX,oCAAG;YACA,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,GAAG;YAChB,KAAK,EAAE,wBAAqB;YAC5B,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,IAAI;YAGhB,uCAAK;cACD,KAAK,EAAE,KAAmB;YAG9B,0CAAQ;cACJ,KAAK,EAAE,KAAmB;UAKjC,uCAAM;YACF,QAAQ,EAAE,OAAO;YACjB,GAAG,EAAE,CAAC;YACN,KAAK,EAAE,IAAI;YACX,gBAAgB,EAAE,OAAO;YACzB,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;YAEb,6CAAQ;cAEJ,QAAQ,EAAE,OAAO;cACjB,IAAI,EAAE,CAAC;cAGP,kEAAmB;gBACf,WAAW,EAAE,GAAG;gBACf,uEAAK;kBACF,WAAW,EAAE,GAAG;kBAChB,YAAY,EAAE,IAAI;YAK9B,6CAAQ;cAEJ,QAAQ,EAAE,OAAO;cACjB,IAAI,EAAE,CAAC;cAGP,uEAAwB;gBACpB,WAAW,EAAE,GAAG;gBAChB,YAAY,EAAE,IAAI;YAG1B,6CAAQ;cAEJ,QAAQ,EAAE,OAAO;cACjB,IAAI,EAAE,CAAC;cAGP,uEAAwB;gBACpB,WAAW,EAAE,GAAG;YAGxB,6CAAQ;cAEJ,QAAQ,EAAE,OAAO;cACjB,IAAI,EAAE,CAAC;cAGP,kEAAmB;gBACf,WAAW,EAAE,GAAG;gBAChB,YAAY,EAAE,IAAI;gBAElB,uEAAK;kBACD,WAAW,EAAE,GAAG;YASxB,iEAAQ;cACJ,MAAM,EAAE,IAAI;cACZ,WAAW,EAAE,IAAI;cACjB,KAAK,EAAE,OAAO;cACd,SAAS,EAAE,IAAI;cACf,WAAW,EAAE,GAAG;cAChB,aAAa,EAAG,cAAc;cAE9B,4EAAa;gBACT,aAAa,EAAE,IAAI;cAGvB,qEAAG;gBACC,OAAO,EAAE,KAAK;gBACd,WAAW,EAAE,GAAG;gBAChB,KAAK,EAAE,IAAI;gBAEX,2EAAQ;kBACL,KAAK,EAjf3B,OAAO;QA6fV,4BAAM;UACF,OAAO,EAAE,KAAK;UACd,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,KAAK;UACV,KAAK,EAAE,IAAI;UACX,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,IAAI;UACZ,UAAU,EAAE,MAAM;UAClB,WAAW,EAAE,IAAI;UACjB,KAAK,EAAE,wBAAqB;UAC5B,SAAS,EAAE,IAAI;UACf,WAAW,EAAE,GAAG;UAChB,MAAM,EAAE,OAAO;UAEhB,aAAa,EAAE,IAAI;UAEnB,kCAAQ;YAAE,KAAK,EAAE,KAAmB;UAEpC,iCAAI;YACA,UAAU,EAAE,IAAI;YAChB,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,IAAI;YACX,gBAAgB,EAAE,kBAAqB;YAEvC,sCAAI;cACA,WAAW,EAAE,IAAI;cAEjB,8CAAU;gBACN,KAAK,EAzhBjB,OAAO;cA2hBC,2CAAO;gBACH,KAAK,EA5hBjB,OAAO;cA8hBC,0CAAG;gBACC,KAAK,EAAE,IAAI;IAQhC,gBAAS;MACL,OAAO,EAAE,IAAI;MACb,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,IAAI;MACT,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,gBAAgB,EAAE,KAAsB;MACxC,aAAa,EAAE,cAAc;AAKxC,QAAS;EACN,QAAQ,EAAE,QAAQ;EAClB,QAAQ,EAAE,MAAM;EAChB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,KAAK;EAEb,uBAAc;IACX,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,OAAO,EAAE,EAAE;IAGR,iCAAI;MACD,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,CAAC;MACN,IAAI,EAAE,CAAC;MACP,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,WAAW,EAAE,QAAQ;MACrB,iBAAiB,EAAE,SAAS;MAC5B,eAAe,EAAE,KAAK;MACtB,mBAAmB,EAAE,OAAO;MAE5B,8CAAe;QACZ,gBAAgB,EAAE,wBAAwB;MAK7C,8CAAe;QACZ,gBAAgB,EAAE,4BAA4B;QAC9C,mBAAmB,EAAE,OAAO;MAI/B,8CAAe;QACZ,gBAAgB,EAAE,4BAA4B;MAKjD,8CAAe;QACZ,gBAAgB,EAAE,4BAA4B;EAQ1D,uBAAc;IACX,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,GAAG;IACR,IAAI,EAAE,GAAG;IACT,SAAS,EAAE,qBAAqB;IAChC,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,KAAK;IACb,gBAAgB,EAAE,kBAAkB;IACpC,UAAU,EAAE,GAAG;IACf,OAAO,EAAE,IAAI;IAKP,iCAAI;MACD,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,GAAG;MACR,IAAI,EAAE,GAAG;MACT,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,SAAS,EAAE,qBAAqB;MAChC,MAAM,EAAE,IAAI;MACZ,UAAU,EAAE,MAAM;MAIf,2CAAI;QACD,QAAQ,EAAE,QAAQ;QAClB,aAAa,EAAE,IAAI;QACnB,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,GAAG;QAChB,KAAK,EAAE,IAAI;QAEX,iDAAQ;UACL,QAAQ,EAAE,QAAQ;UAClB,MAAM,EAAE,KAAK;UACb,IAAI,EAAE,GAAG;UACT,SAAS,EAAE,gBAAgB;UAC3B,KAAK,EAAE,KAAK;UACZ,MAAM,EAAE,GAAG;UACX,gBAAgB,EA7oBxB,OAAO;UA8oBC,OAAO,EAAE,EAAE;MAIjB,2CAAI;QACD,cAAc,EAAE,GAAG;QACnB,WAAW,EAAE,KAAK;QAClB,SAAS,EAAE,IAAI;QACf,KAAK,EAAE,IAAI;EAQ7B,6BAAoB;IACjB,QAAQ,EAAE,QAAQ;IAClB,GAAG,EAAE,GAAG;IACR,IAAI,EAAE,GAAG;IACT,SAAS,EAAE,qBAAqB;IAChC,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,KAAK;IACb,OAAO,EAAE,IAAI;IAEb,mCAAQ;MACL,QAAQ,EAAE,QAAQ;MAClB,MAAM,EAAE,IAAI;MACZ,KAAK,EAAE,IAAI;MACX,KAAK,EAAE,GAAG;MACV,MAAM,EAAE,GAAG;MACX,gBAAgB,EA7qBT,OAAO;MA8qBd,aAAa,EAAE,GAAG;MAClB,OAAO,EAAE,EAAE;IAId,iCAAG;MACA,OAAO,EAAE,KAAK;MACd,QAAQ,EAAE,QAAQ;MAClB,MAAM,EAAE,IAAI;MACZ,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,WAAW,EAAE,QAAQ;MACrB,UAAU,EAAE,GAAG;MAEf,MAAM,EAAE,OAAO;MACf,iBAAiB,EAAE,SAAS;MAC5B,eAAe,EAAE,KAAK;MAEtB,kDAAmB;QAChB,gBAAgB,EAAE,2BAA2B;QAC7C,KAAK,EAAC,IAAI;QAEV,wDAAQ;UACL,gBAAgB,EAAE,iCAAiC;MAIzD,kDAAmB;QAChB,gBAAgB,EAAE,2BAA2B;QAC7C,KAAK,EAAE,IAAI;QAEX,wDAAQ;UACL,gBAAgB,EAAE,iCAAiC;EAO/D,qBAAY;IACT,QAAQ,EAAE,QAAQ;IAClB,MAAM,EAAE,IAAI;IACZ,IAAI,EAAE,GAAG;IACT,SAAS,EAAE,8BAA8B;IACzC,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,OAAO;IACf,gBAAgB,EAAE,2BAA2B;IAC7C,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,OAAO;IAC5B,SAAS,EAAE,uBAAwB;;AAOzC,oCAAsC;EAAC,eAAe;EAClD,QAAS;IACN,QAAQ,EAAE,QAAQ;IAClB,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,KAAK;IAEb,uBAAc;MACX,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,OAAO,EAAE,EAAE;MAGR,iCAAI;QACD,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,QAAQ;QACrB,iBAAiB,EAAE,SAAS;QAC5B,eAAe,EAAE,KAAK;QACtB,mBAAmB,EAAE,OAAO;QAE5B,8CAAe;UACZ,gBAAgB,EAAE,wBAAwB;QAK7C,8CAAe;UACZ,gBAAgB,EAAE,4BAA4B;UAC9C,mBAAmB,EAAE,OAAO;QAI/B,8CAAe;UACZ,gBAAgB,EAAE,4BAA4B;QAKjD,8CAAe;UACZ,gBAAgB,EAAE,4BAA4B;IAQ1D,uBAAc;MACX,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,GAAG;MACR,IAAI,EAAE,GAAG;MACT,SAAS,EAAE,qBAAqB;MAChC,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,KAAK;MACb,gBAAgB,EAAE,kBAAkB;MACpC,UAAU,EAAE,GAAG;MACf,OAAO,EAAE,IAAI;MAKP,iCAAI;QACD,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,GAAG;QACR,IAAI,EAAE,GAAG;QACT,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,SAAS,EAAE,qBAAqB;QAChC,MAAM,EAAE,IAAI;QACZ,UAAU,EAAE,MAAM;QAIf,2CAAI;UACD,QAAQ,EAAE,QAAQ;UAClB,aAAa,EAAE,IAAI;UACnB,SAAS,EAAE,IAAI;UACf,WAAW,EAAE,GAAG;UAChB,KAAK,EAAE,IAAI;UAEX,iDAAQ;YACL,QAAQ,EAAE,QAAQ;YAClB,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,GAAG;YACT,SAAS,EAAE,gBAAgB;YAC3B,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,GAAG;YACX,gBAAgB,EAl0B5B,OAAO;YAm0BK,OAAO,EAAE,EAAE;QAIjB,2CAAI;UACD,cAAc,EAAE,GAAG;UACnB,WAAW,EAAE,KAAK;UAClB,SAAS,EAAE,IAAI;UACf,KAAK,EAAE,IAAI;IAQ7B,6BAAoB;MACjB,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,GAAG;MACR,IAAI,EAAE,GAAG;MACT,SAAS,EAAE,qBAAqB;MAChC,KAAK,EAAE,KAAK;MACZ,MAAM,EAAE,KAAK;MACb,OAAO,EAAE,IAAI;MAEb,mCAAQ;QACL,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,GAAG;QACT,SAAS,EAAE,gBAAgB;QAC3B,KAAK,EAAE,GAAG;QACV,MAAM,EAAE,GAAG;QACX,gBAAgB,EAn2Bb,OAAO;QAo2BV,aAAa,EAAE,GAAG;QAClB,OAAO,EAAE,EAAE;MAId,iCAAG;QACA,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,IAAI;QACZ,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,QAAQ;QACrB,UAAU,EAAE,GAAG;QAEf,MAAM,EAAE,OAAO;QACf,iBAAiB,EAAE,SAAS;QAC5B,eAAe,EAAE,OAAO;QAExB,kDAAmB;UAChB,gBAAgB,EAAE,2BAA2B;UAC7C,mBAAmB,EAAE,QAAQ;UAC7B,IAAI,EAAE,GAAG;UAET,wDAAQ;YACL,gBAAgB,EAAE,iCAAiC;QAIzD,kDAAmB;UAChB,gBAAgB,EAAE,2BAA2B;UAC7C,IAAI,EAAE,GAAG;UAET,wDAAQ;YACL,gBAAgB,EAAE,iCAAiC;IAO/D,qBAAY;MACT,QAAQ,EAAE,QAAQ;MAClB,MAAM,EAAE,IAAI;MACZ,IAAI,EAAE,GAAG;MACT,SAAS,EAAE,8BAA8B;MACzC,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,MAAM,EAAE,OAAO;MACf,gBAAgB,EAAE,2BAA2B;MAC7C,iBAAiB,EAAE,SAAS;MAC5B,mBAAmB,EAAE,OAAO;MAC5B,SAAS,EAAE,uBAAwB;AAW7C,QAAS;EACN,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,IAAI;EAGV,iBAAQ;AA8JN;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SA2CG;IAvMF,sBAAI;MACD,QAAQ,EAAE,QAAQ;MAClB,OAAO,EAAE,QAAQ;MACjB,WAAW,EAAE,GAAG;MAChB,UAAU,EAAE,MAAM;MAClB,KAAK,EAAE,IAAI;MACX,cAAc,EAAE,SAAS;MAEzB,4BAAQ;QACL,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,GAAG;QACT,SAAS,EAAE,gBAAgB;QAC3B,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,GAAG;QAChB,KAAK,EAz7BH,OAAO;QA07BT,cAAc,EAAE,MAAM;QACtB,OAAO,EAAE,gBAAgB;IAK/B,gCAAc;MAEV,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,KAAK;MACb,MAAM,EAAE,WAAW;MACnB,gBAAgB,EAAE,wBAAwB;MAC1C,mBAAmB,EAAG,OAAO;MAC7B,eAAe,EAAE,OAAO;MACxB,iBAAiB,EAAE,SAAS;IAIhC,kCAAgB;MAEZ,MAAM,EAAG,WAAW;MACpB,UAAU,EAAE,IAAI;MAChB,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,GAAG;MAChB,WAAW,EAAE,KAAK;MAGlB,+CAAY;QACR,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,KAAK;QACZ,UAAU,EAAE,KAAK;QACjB,UAAU,EAAE,KAAK;QAEjB,qDAAQ;UACJ,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,IAAI;UACT,KAAK,EAAG,CAAC;UACT,KAAK,EAAE,GAAG;UACV,MAAM,EAAE,KAAK;UACb,gBAAgB,EAAE,OAAO;UACzB,OAAO,EAAE,EAAE;QAGf,oDAAI;UACA,aAAa,EAAE,IAAI;UAKX,mEAAI;YACA,SAAS,EAAE,IAAI;YACf,aAAa,EAAE,GAAG;YAClB,KAAK,EAAE,OAAkB;UAE7B,mEAAI;YACA,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,GAAG;YAChB,KAAK,EAp/BrB,OAAO;QA4/BP,oDAAI;UACA,SAAS,EAAE,IAAI;UACf,UAAU,EAAE,IAAI;UAChB,aAAa,EAAE,IAAI;UACnB,WAAW,EAAE,GAAG;UAEhB,yDAAI;YACA,WAAW,EAAE,GAAG;YAGR,wEAAI;cACA,KAAK,EAAE,OAAO;MAUtC,+CAAY;QACR,KAAK,EAAE,IAAI;QACX,KAAK,EAAE,KAAK;QACZ,UAAU,EAAE,IAAI;QAEhB,oDAAI;UACA,YAAY,EAAE,IAAI;UAClB,MAAM,EAAE,KAAK;UAGb,yDAAI;YACA,aAAa,EAAE,GAAG;YAClB,KAAK,EAAE,KAAK;YACZ,gBAAgB,EA9hCxB,OAAO;YAgiCC,UAAU,EAAE,GAAG;YACf,MAAM,EAAE,IAAI;YAEZ,6DAAG;cACC,OAAO,EAAE,KAAK;cACd,YAAY,EAAE,IAAI;cAClB,WAAW,EAAE,GAAG;cAChB,SAAS,EAAE,IAAI;cACf,cAAc,EAAE,EAAE;cAClB,WAAW,EAAE,IAAI;cACjB,MAAM,EAAE,IAAI;cACZ,KAAK,EAAE,IAAI;cACX,UAAU,EAAE,GAAG;YAGnB,+DAAQ;cACJ,gBAAgB,EA/iC3B,OAAO;YAujCA,iEAAU;cACN,KAAK,EAAE,OAAO;;AA4DzC,oCAAqC;EAAC,eAAe;EACjD,QAAS;IACN,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,IAAI;IAKP,sBAAI;MACD,QAAQ,EAAE,QAAQ;MAClB,OAAO,EAAE,QAAQ;MACjB,WAAW,EAAE,GAAG;MAChB,UAAU,EAAE,MAAM;MAClB,KAAK,EAAE,IAAI;MACX,cAAc,EAAE,SAAS;MAEzB,4BAAQ;QACL,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,GAAG;QACT,SAAS,EAAE,gBAAgB;QAC3B,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,GAAG;QAChB,KAAK,EA5oCP,OAAO;QA6oCL,cAAc,EAAE,MAAM;QACtB,OAAO,EAAE,gBAAgB;IAK/B,gCAAc;MACV,OAAO,EAAE,IAAI;MAEb,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,KAAK;MACb,MAAM,EAAE,WAAW;MACnB,gBAAgB,EAAE,wBAAwB;MAC1C,mBAAmB,EAAG,OAAO;MAC7B,eAAe,EAAE,OAAO;MACxB,iBAAiB,EAAE,SAAS;IAIhC,kCAAgB;MACZ,KAAK,EAAE,IAAI;MACX,MAAM,EAAG,WAAW;MACpB,UAAU,EAAE,MAAM;MAClB,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,GAAG;MAChB,WAAW,EAAE,KAAK;MAGlB,+CAAY;QACR,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,GAAG;QACf,WAAW,EAAE,IAAI;QACjB,UAAU,EAAE,MAAM;QAElB,qDAAQ;UACJ,OAAO,EAAE,IAAI;UACb,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,IAAI;UACT,KAAK,EAAG,CAAC;UACT,KAAK,EAAE,GAAG;UACV,MAAM,EAAE,KAAK;UACb,gBAAgB,EAAE,OAAO;UACzB,OAAO,EAAE,EAAE;QAGf,oDAAI;UACA,aAAa,EAAE,GAAG;UAKV,mEAAI;YACA,SAAS,EAAE,IAAI;YACf,aAAa,EAAE,GAAG;YAClB,KAAK,EAAE,OAAkB;UAE7B,mEAAI;YACA,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,GAAG;YAChB,KAAK,EA1sCzB,OAAO;QAktCH,oDAAI;UACA,SAAS,EAAE,IAAI;UACf,UAAU,EAAE,IAAI;UAEhB,OAAO,EAAE,KAAK;UACd,WAAW,EAAE,GAAG;UAEhB,yDAAI;YACA,WAAW,EAAE,MAAM;YAGX,wEAAI;cACA,KAAK,EAAE,OAAO;MAUtC,+CAAY;QACR,KAAK,EAAE,OAAO;QACd,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,IAAI;QACjB,UAAU,EAAE,MAAM;QAElB,oDAAI;UACA,YAAY,EAAE,GAAG;UACjB,MAAM,EAAE,IAAI;UAGZ,yDAAI;YACA,MAAM,EAAE,UAAU;YAElB,KAAK,EAAE,GAAG;YACV,gBAAgB,EAvvC5B,OAAO;YAyvCK,UAAU,EAAE,GAAG;YACf,MAAM,EAAE,IAAI;YAEZ,6DAAG;cACC,OAAO,EAAE,KAAK;cACd,YAAY,EAAE,IAAI;cAClB,WAAW,EAAE,GAAG;cAChB,SAAS,EAAE,IAAI;cACf,cAAc,EAAE,GAAG;cACnB,WAAW,EAAE,IAAI;cACjB,MAAM,EAAE,IAAI;cACZ,KAAK,EAAE,IAAI;cACX,UAAU,EAAE,GAAG;YAGnB,+DAAQ;cACJ,gBAAgB,EAxwC/B,OAAO;YAgxCI,iEAAU;cACN,KAAK,EAAE,OAAO;AAiB7C,QAAS;EACN,UAAU,EAAE,IAAI;EAChB,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,KAAK;EAEb,eAAe,EAAE,KAAK;EACtB,iBAAiB,EAAE,SAAS;EAC5B,mBAAmB,EAAE,OAAO;EAG1B,iBAAQ;IACH,QAAQ,EAAE,QAAQ;IAAC,sBAAsB;IAG5C,sBAAI;MACD,QAAQ,EAAE,QAAQ;MAClB,OAAO,EAAE,QAAQ;MACjB,WAAW,EAAE,GAAG;MAChB,UAAU,EAAE,MAAM;MAClB,KAAK,EAAE,IAAI;MACX,cAAc,EAAE,SAAS;MAEzB,4BAAQ;QACL,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,GAAG;QACT,SAAS,EAAE,gBAAgB;QAC3B,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,GAAG;QAChB,KAAK,EAh0CH,OAAO;QAi0CT,cAAc,EAAE,GAAG;QACnB,OAAO,EAAE,eAAe;IAI9B,gCAAc;MACV,QAAQ,EAAE,QAAQ;MAAC,8BAA8B;MACjD,QAAQ,EAAE,MAAM;MAChB,KAAK,EAAE,MAAM;MACb,MAAM,EAAE,KAAK;MACb,MAAM,EAAE,WAAW;MAGnB,qDAAoB;QAChB,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,GAAG;QACR,IAAI,EAAE,CAAC;QACP,KAAK,EAAE,MAAM;QAEb,2DAAK;UACD,KAAK,EAAE,IAAI;UACX,KAAK,EAAE,MAAM;UACb,MAAM,EAAE,IAAI;UAEZ,gEAAI;YACA,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,MAAM;YAGd,qEAAI;cAEA,QAAQ,EAAE,QAAQ;cAClB,KAAK,EAAE,IAAI;cACX,WAAW,EAAE,IAAI;cACjB,KAAK,EAAE,KAAK;cACZ,MAAM,EAAE,KAAK;cACb,UAAU,EAAE,GAAG;cACf,gBAAgB,EAAE,IAAI;cACtB,aAAa,EAAE,GAAG;cAIlB,2EAAQ;gBACJ,OAAO,EAAE,CAAC;gBACV,QAAQ,EAAE,QAAQ;gBAClB,GAAG,EAAE,KAAK;gBACV,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,iBAAsB;gBAC9B,UAAU,EAAE,GAAG;gBACf,OAAO,EAAE,EAAE;cAKf,iFAAc;gBAAC,OAAO,EAAE,CAAC;cAKrB,+EAAI;gBACA,MAAM,EAAE,aAAa;gBACrB,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,KAAK;gBAEb,mBAAmB,EAAE,OAAO;gBAC5B,eAAe,EAAE,OAAO;gBACxB,iBAAiB,EAAE,SAAS;gBAC5B,UAAU,EAAE,GAAG;gBAGf,mFAAG;kBACC,OAAO,EAAE,KAAK;kBACd,WAAW,EAAE,QAAQ;kBACrB,MAAM,EAAE,QAAQ;kBAChB,WAAW,EAAE,IAAI;kBACjB,KAAK,EAAE,IAAI;kBACX,MAAM,EAAE,IAAI;kBACZ,mBAAmB,EAAE,OAAO;kBAC5B,eAAe,EAAE,OAAO;kBACxB,iBAAiB,EAAE,SAAS;kBAC5B,UAAU,EAAE,GAAG;cAIvB,mFAAQ;gBACJ,MAAM,EAAE,KAAK;gBACb,KAAK,EAAE,IAAI;gBACX,MAAM,EAAE,IAAI;gBACZ,SAAS,EAAE,IAAI;gBACf,WAAW,EAAE,GAAG;gBAChB,UAAU,EAAE,MAAM;gBAClB,WAAW,EAAE,IAAI;gBACjB,UAAU,EAAE,GAAG;gBACf,KAAK,EAAE,IAAI;cAIf,kFAAO;gBACH,KAAK,EAAE,IAAI;gBACX,UAAU,EAAE,KAAK;gBACjB,WAAW,EAAE,KAAK;gBAClB,cAAc,EAAE,IAAI;gBACpB,SAAS,EAAE,IAAI;gBACf,WAAW,EAAE,GAAG;gBAChB,UAAU,EAAE,MAAM;gBAClB,UAAU,EAAE,GAAG;gBACf,KAAK,EAAE,IAAI;cAIf,kFAAO;gBAEH,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,UAAU;gBAClB,UAAU,EAAE,MAAM;gBAClB,WAAW,EAAE,GAAG;gBAChB,KAAK,EAv7CxB,OAAO;gBAw7CY,OAAO,EAAE,IAAI;gBAEb,uFAAI;kBACA,KAAK,EA57C7B,OAAO;gBA+7Ca,sFAAG;kBACC,QAAQ,EAAE,QAAQ;kBAClB,GAAG,EAAE,CAAC;kBACN,IAAI,EAAE,CAAC;kBACP,OAAO,EAAE,KAAK;kBACd,KAAK,EAAE,KAAK;kBACZ,MAAM,EAAE,KAAK;kBACb,KAAK,EAAE,IAAI;kBAEX,OAAO,EAAE,IAAI;QAa5B,2FAAiB;UAAC,gBAAgB,EAAE,yBAAyB;QAC7D,2FAAiB;UAAC,gBAAgB,EAAE,yBAAyB;QAC7D,2FAAiB;UAAC,gBAAgB,EAAE,yBAAyB;QAC7D,2FAAiB;UAAC,gBAAgB,EAAE,yBAAyB;QAItE,kEAAY;UACR,OAAO,EAAE,IAAI;UAGb,4EAAQ;YACJ,eAAe,EAAE,GAAG;IAapC,sCAAoB;MACjB,QAAQ,EAAE,QAAQ;MAClB,MAAM,EAAE,KAAK;MACb,IAAI,EAAE,GAAG;MACT,SAAS,EAAE,gBAAgB;MAC3B,KAAK,EAAE,KAAK;MACZ,MAAM,EAAE,IAAI;MAKR,gDAAI;QACA,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,IAAI;QACjB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,gBAAgB,EAAE,IAAI;QACtB,aAAa,EAAE,IAAI;QACnB,MAAM,EAAE,OAAO;QAEf,mDAAK;UACD,gBAAgB,EAAE,IAAI;IAMrC,mCAAiB;MACb,OAAO,EAAE,IAAI;MACb,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,GAAG;MACR,KAAK,EAAE,IAAI;MAEX,uCAAG;QACC,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,CAAC;QACN,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,QAAQ;QAErB,MAAM,EAAE,OAAO;MAGnB,2CAAO;QACH,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,KAAK;QAEX,iDAAQ;UACJ,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,GAAG;UACR,IAAI,EAAE,KAAK;UACX,SAAS,EAAE,cAAc;UACzB,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,GAAG;UACX,gBAAgB,EApiDpB,OAAO;UAqiDH,OAAO,EAAE,EAAE;QAEf,kDAAS;UACL,QAAQ,EAAE,QAAQ;UAClB,MAAM,EAAE,GAAG;UACX,IAAI,EAAE,KAAK;UACX,SAAS,EAAE,aAAa;UACxB,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,GAAG;UACX,gBAAgB,EA9iDpB,OAAO;UA+iDH,OAAO,EAAE,EAAE;MAInB,2CAAO;QACH,QAAQ,EAAE,QAAQ;QAClB,KAAK,EAAE,KAAK;QAEZ,iDAAQ;UACJ,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,GAAG;UACR,IAAI,EAAE,IAAI;UACV,SAAS,EAAE,aAAa;UACxB,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,GAAG;UACX,gBAAgB,EA9jDpB,OAAO;UA+jDH,OAAO,EAAE,EAAE;QAEf,kDAAS;UACL,QAAQ,EAAE,QAAQ;UAClB,MAAM,EAAE,GAAG;UACX,IAAI,EAAE,IAAI;UACV,SAAS,EAAE,cAAc;UACzB,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,GAAG;UACX,gBAAgB,EAxkDpB,OAAO;UAykDH,OAAO,EAAE,EAAE;;AAO9B,oCAAsC;EAAC,qBAAqB;EACxD,QAAS;IACN,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IAEZ,eAAe,EAAE,KAAK;IACtB,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,OAAO;IAG1B,iBAAQ;MACH,QAAQ,EAAE,QAAQ;MAAC,sBAAsB;MAG5C,sBAAI;QACD,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,QAAQ;QACjB,WAAW,EAAE,GAAG;QAChB,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,IAAI;QACX,cAAc,EAAE,SAAS;QAEzB,4BAAQ;UACL,QAAQ,EAAE,QAAQ;UAClB,MAAM,EAAE,KAAK;UACb,IAAI,EAAE,GAAG;UACT,SAAS,EAAE,gBAAgB;UAC3B,SAAS,EAAE,IAAI;UACf,WAAW,EAAE,GAAG;UAChB,KAAK,EA9mDP,OAAO;UA+mDL,cAAc,EAAE,GAAG;UACnB,OAAO,EAAE,eAAe;MAI9B,gCAAc;QACV,QAAQ,EAAE,QAAQ;QAAC,8BAA8B;QACjD,QAAQ,EAAE,MAAM;QAChB,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,KAAK;QACb,MAAM,EAAE,SAAS;QAGjB,qDAAoB;UAChB,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,GAAG;UACR,IAAI,EAAE,CAAC;UACP,KAAK,EAAE,MAAM;UAEb,2DAAK;YACD,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,IAAI;YAEZ,gEAAI;cACA,KAAK,EAAE,MAAM;cACb,MAAM,EAAE,MAAM;cAGd,qEAAI;gBAEA,QAAQ,EAAE,QAAQ;gBAClB,KAAK,EAAE,IAAI;gBACX,WAAW,EAAE,GAAG;gBAChB,KAAK,EAAE,KAAK;gBACZ,MAAM,EAAE,KAAK;gBACb,UAAU,EAAE,GAAG;gBACf,gBAAgB,EAAE,IAAI;gBACtB,aAAa,EAAE,GAAG;gBAIlB,2EAAQ;kBACJ,OAAO,EAAE,CAAC;kBACV,QAAQ,EAAE,QAAQ;kBAClB,GAAG,EAAE,IAAI;kBACT,IAAI,EAAE,IAAI;kBACV,KAAK,EAAE,KAAK;kBACZ,MAAM,EAAE,KAAK;kBACb,MAAM,EAAE,iBAAsB;kBAC9B,UAAU,EAAE,GAAG;kBACf,OAAO,EAAE,EAAE;gBAKf,iFAAc;kBAAC,OAAO,EAAE,CAAC;gBAKrB,+EAAI;kBACA,MAAM,EAAE,aAAa;kBACrB,KAAK,EAAE,KAAK;kBACZ,MAAM,EAAE,KAAK;kBAEb,mBAAmB,EAAE,OAAO;kBAC5B,eAAe,EAAE,OAAO;kBACxB,iBAAiB,EAAE,SAAS;kBAC5B,UAAU,EAAE,GAAG;kBAGf,mFAAG;oBACC,OAAO,EAAE,KAAK;oBACd,WAAW,EAAE,QAAQ;oBACrB,MAAM,EAAE,QAAQ;oBAChB,WAAW,EAAE,IAAI;oBACjB,KAAK,EAAE,IAAI;oBACX,MAAM,EAAE,IAAI;oBACZ,mBAAmB,EAAE,OAAO;oBAC5B,eAAe,EAAE,OAAO;oBACxB,iBAAiB,EAAE,SAAS;oBAC5B,UAAU,EAAE,GAAG;gBAIvB,mFAAQ;kBACJ,MAAM,EAAE,KAAK;kBACb,KAAK,EAAE,IAAI;kBACX,MAAM,EAAE,IAAI;kBACZ,SAAS,EAAE,IAAI;kBACf,WAAW,EAAE,GAAG;kBAChB,UAAU,EAAE,MAAM;kBAClB,WAAW,EAAE,IAAI;kBACjB,UAAU,EAAE,GAAG;kBACf,KAAK,EAAE,IAAI;gBAIf,kFAAO;kBACH,KAAK,EAAE,IAAI;kBACX,UAAU,EAAE,KAAK;kBACjB,WAAW,EAAE,KAAK;kBAClB,cAAc,EAAE,IAAI;kBACpB,SAAS,EAAE,IAAI;kBACf,WAAW,EAAE,GAAG;kBAChB,UAAU,EAAE,MAAM;kBAClB,UAAU,EAAE,GAAG;kBACf,KAAK,EAAE,IAAI;gBAIf,kFAAO;kBAEH,OAAO,EAAE,KAAK;kBACd,KAAK,EAAE,KAAK;kBACZ,MAAM,EAAE,UAAU;kBAClB,UAAU,EAAE,MAAM;kBAClB,WAAW,EAAE,GAAG;kBAChB,KAAK,EAruD5B,OAAO;kBAsuDgB,OAAO,EAAE,IAAI;kBAEb,uFAAI;oBACA,KAAK,EA1uDjC,OAAO;kBA6uDiB,sFAAG;oBACC,QAAQ,EAAE,QAAQ;oBAClB,GAAG,EAAE,CAAC;oBACN,IAAI,EAAE,CAAC;oBACP,OAAO,EAAE,KAAK;oBACd,KAAK,EAAE,IAAI;oBACX,MAAM,EAAE,KAAK;oBACb,KAAK,EAAE,IAAI;oBAEX,OAAO,EAAE,IAAI;UAa5B,2FAAiB;YAAC,gBAAgB,EAAE,yBAAyB;UAC7D,2FAAiB;YAAC,gBAAgB,EAAE,yBAAyB;UAC7D,2FAAiB;YAAC,gBAAgB,EAAE,yBAAyB;UAC7D,2FAAiB;YAAC,gBAAgB,EAAE,yBAAyB;UAItE,kEAAY;YACR,OAAO,EAAE,IAAI;YAGb,4EAAQ;cACJ,eAAe,EAAE,GAAG;MAepC,mCAAiB;QACb,OAAO,EAAE,KAAK;QACd,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,GAAG;QACR,KAAK,EAAE,IAAI;QAEX,uCAAG;UACC,QAAQ,EAAE,QAAQ;UAClB,GAAG,EAAE,KAAK;UACV,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,IAAI;UACZ,WAAW,EAAE,QAAQ;UACrB,OAAO,EAAE,IAAI;UAEb,MAAM,EAAE,OAAO;QAGnB,2CAAO;UACH,QAAQ,EAAE,QAAQ;UAClB,IAAI,EAAE,IAAI;UAEV,iDAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,IAAI;YACV,SAAS,EAAE,cAAc;YACzB,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,GAAG;YACX,gBAAgB,EA1zDxB,OAAO;YA2zDC,OAAO,EAAE,EAAE;UAEf,kDAAS;YACL,QAAQ,EAAE,QAAQ;YAClB,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,IAAI;YACV,SAAS,EAAE,aAAa;YACxB,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,GAAG;YACX,gBAAgB,EAp0DxB,OAAO;YAq0DC,OAAO,EAAE,EAAE;QAGnB,2CAAO;UACH,QAAQ,EAAE,QAAQ;UAClB,KAAK,EAAE,IAAI;UAEX,iDAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,IAAI;YACV,SAAS,EAAE,aAAa;YACxB,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,GAAG;YACX,gBAAgB,EAn1DxB,OAAO;YAo1DC,OAAO,EAAE,EAAE;UAEf,kDAAS;YACL,QAAQ,EAAE,QAAQ;YAClB,MAAM,EAAE,GAAG;YACX,IAAI,EAAE,IAAI;YACV,SAAS,EAAE,cAAc;YACzB,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,GAAG;YACX,gBAAgB,EA71DxB,OAAO;YA81DC,OAAO,EAAE,EAAE;AAQlC,eAAgB;EACZ,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,KAAK;EACb,gBAAgB,EAAE,uBAAuB;EACzC,qBAAqB,EAAE,KAAK;EAC5B,iBAAiB,EAAE,SAAS;EAC5B,mBAAmB,EAAE,OAAO;EAC5B,eAAe,EAAE,KAAK;EAEtB,wBAAQ;IACJ,WAAW,EAAE,IAAI;IAEjB,6BAAI;MACA,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,KAAK;MAGb,kCAAI;QACA,KAAK,EAAE,KAAK;QACZ,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,IAAI;QAGf,+CAAe;UACX,WAAW,EAAE,KAAK;QAGtB,+CAAe;UACX,QAAQ,EAAE,QAAQ;UAElB,qDAAQ;YACJ,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,CAAC;YACP,KAAK,EAAE,GAAG;YACV,MAAM,EAAE,IAAI;YACZ,gBAAgB,EAAE,IAAI;YACtB,OAAO,EAAE,EAAE;UAGf,sDAAS;YACL,QAAQ,EAAE,QAAQ;YAClB,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,CAAC;YACR,KAAK,EAAE,GAAG;YACV,MAAM,EAAE,IAAI;YACZ,gBAAgB,EAAE,IAAI;YACtB,OAAO,EAAE,EAAE;UAGf,yDAAO;YACH,cAAc,EAAE,IAAI;QAOxB,4CAAI;UACA,SAAS,EAAE,IAAI;UACf,WAAW,EAAE,GAAG;UAChB,KAAK,EAp6Db,OAAO;UAq6DC,aAAa,EAAE,IAAI;UAEnB,mDAAM;YACF,SAAS,EAAE,IAAI;QAIvB,4CAAI;UACA,SAAS,EAAE,IAAI;;AAQvC,oCAAqC;EAAC,4BAA4B;EAC9D,eAAgB;IACZ,OAAO,EAAE,IAAI;IACb,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,KAAK;IACb,gBAAgB,EAAE,uBAAuB;IACzC,qBAAqB,EAAE,KAAK;IAC5B,iBAAiB,EAAE,SAAS;IAC5B,mBAAmB,EAAE,OAAO;IAC5B,eAAe,EAAE,KAAK;IAEtB,wBAAQ;MACJ,WAAW,EAAE,IAAI;MAEjB,6BAAI;QACA,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,KAAK;QAGb,kCAAI;UACA,KAAK,EAAE,KAAK;UACZ,KAAK,EAAE,IAAI;UACX,UAAU,EAAE,MAAM;UAClB,KAAK,EAAE,IAAI;UACX,SAAS,EAAE,IAAI;UAGf,+CAAe;YACX,WAAW,EAAE,KAAK;UAGtB,+CAAe;YACX,QAAQ,EAAE,QAAQ;YAElB,qDAAQ;cACJ,QAAQ,EAAE,QAAQ;cAClB,GAAG,EAAE,GAAG;cACR,IAAI,EAAE,CAAC;cACP,KAAK,EAAE,GAAG;cACV,MAAM,EAAE,IAAI;cACZ,gBAAgB,EAAE,IAAI;cACtB,OAAO,EAAE,EAAE;YAGf,sDAAS;cACL,QAAQ,EAAE,QAAQ;cAClB,GAAG,EAAE,GAAG;cACR,KAAK,EAAE,CAAC;cACR,KAAK,EAAE,GAAG;cACV,MAAM,EAAE,IAAI;cACZ,gBAAgB,EAAE,IAAI;cACtB,OAAO,EAAE,EAAE;YAGf,yDAAO;cACH,cAAc,EAAE,IAAI;UAOxB,4CAAI;YACA,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,GAAG;YAChB,KAAK,EAt/DjB,OAAO;YAu/DK,aAAa,EAAE,IAAI;YAEnB,mDAAM;cACF,SAAS,EAAE,IAAI;UAIvB,4CAAI;YACA,SAAS,EAAE,IAAI;AAa3C,QAAS;EACN,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,KAAK;EACb,gBAAgB,EAhhEJ,OAAO;EAkhEnB,aAAI;IACD,QAAQ,EAAE,QAAQ;IAClB,OAAO,EAAE,QAAQ;IACjB,WAAW,EAAE,GAAG;IAChB,UAAU,EAAE,MAAM;IAClB,KAAK,EAAE,IAAI;IACX,cAAc,EAAE,SAAS;IAEzB,mBAAQ;MACL,QAAQ,EAAE,QAAQ;MAClB,MAAM,EAAE,KAAK;MACb,IAAI,EAAE,KAAK;MACX,SAAS,EAAE,gBAAgB;MAC3B,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,GAAG;MAChB,KAAK,EAAE,IAAI;MACX,cAAc,EAAE,GAAG;MACnB,OAAO,EAAE,aAAa;EAI5B,wBAAe;IACZ,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,KAAK;IACb,MAAM,EAAE,eAAe;IAEvB,+BAAM;MACD,KAAK,EAAG,KAAK;MACb,MAAM,EAAG,KAAK;MAEd,gBAAgB,EAAE,+BAA+B;MACjD,mBAAmB,EAAE,OAAO;MAC5B,eAAe,EAAE,KAAK;MACtB,MAAM,EAAG,CAAC;MAEV,mCAAG;QACD,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,QAAQ;EAK/B,mBAAU;IACP,QAAQ,EAAE,QAAQ;IAClB,KAAK,EAAE,IAAI;IACX,UAAU,EAAE,MAAM;IAElB,yBAAQ;MACL,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,CAAC;MACN,IAAI,EAAE,GAAG;MACT,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,gBAAgB,EAAE,2BAA2B;MAC7C,mBAAmB,EAAE,KAAK;MAC1B,OAAO,EAAE,EAAE;IAGd,0BAAS;MACN,QAAQ,EAAE,QAAQ;MAClB,MAAM,EAAE,CAAC;MACT,KAAK,EAAE,GAAG;MACV,KAAK,EAAE,IAAI;MACX,MAAM,EAAE,IAAI;MACZ,gBAAgB,EAAE,2BAA2B;MAC7C,mBAAmB,EAAE,SAAS;MAC9B,OAAO,EAAE,EAAE;IAMR,sCAAI;MACD,SAAS,EAAE,IAAI;MACf,WAAW,EAAE,GAAG;MAChB,KAAK,EAAE,IAAI;MACX,WAAW,EAAE,KAAK;MAElB,6CAAM;QACH,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,GAAG;;AAUlC,oCAAqC;EAAC,qBAAqB;EAEvD,QAAS;IACN,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAnnER,OAAO;IAqnEf,aAAI;MACD,QAAQ,EAAE,QAAQ;MAClB,OAAO,EAAE,QAAQ;MACjB,WAAW,EAAE,GAAG;MAChB,UAAU,EAAE,MAAM;MAClB,KAAK,EAAE,IAAI;MACX,cAAc,EAAE,SAAS;MAEzB,mBAAQ;QACL,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,KAAK;QACX,SAAS,EAAE,gBAAgB;QAC3B,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,GAAG;QAChB,KAAK,EAAE,IAAI;QACX,cAAc,EAAE,GAAG;QACnB,OAAO,EAAE,aAAa;IAI5B,wBAAe;MACZ,KAAK,EAAE,GAAG;MACV,MAAM,EAAE,KAAK;MACb,MAAM,EAAE,cAAc;MAEtB,+BAAM;QACD,KAAK,EAAG,IAAI;QACZ,MAAM,EAAG,KAAK;QAEd,gBAAgB,EAAE,+BAA+B;QACjD,mBAAmB,EAAE,OAAO;QAC5B,eAAe,EAAE,KAAK;QACtB,MAAM,EAAG,CAAC;QAEV,mCAAG;UACD,OAAO,EAAE,KAAK;UACd,KAAK,EAAE,IAAI;UACX,MAAM,EAAE,IAAI;UACZ,WAAW,EAAE,QAAQ;IAK/B,mBAAU;MACP,QAAQ,EAAE,QAAQ;MAClB,KAAK,EAAE,IAAI;MACX,UAAU,EAAE,MAAM;MAClB,cAAc,EAAE,IAAI;MAEpB,yBAAQ;QACL,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,CAAC;QACN,IAAI,EAAE,GAAG;QACT,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,gBAAgB,EAAE,2BAA2B;QAC7C,mBAAmB,EAAE,KAAK;QAC1B,OAAO,EAAE,EAAE;MAGd,0BAAS;QACN,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,CAAC;QACT,KAAK,EAAE,GAAG;QACV,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;QACZ,gBAAgB,EAAE,2BAA2B;QAC7C,mBAAmB,EAAE,SAAS;QAC9B,OAAO,EAAE,EAAE;MAMR,sCAAI;QACD,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,GAAG;QAChB,KAAK,EAAE,IAAI;QACX,WAAW,EAAE,KAAK;QAElB,6CAAM;UACH,OAAO,EAAE,KAAK;UACd,KAAK,EAAE,IAAI;UACX,WAAW,EAAE,GAAG;AAWtC,MAAO;EACJ,KAAK,EAAE,IAAI;EACX,MAAM,EAAE,KAAK;EACb,gBAAgB,EAAE,IAAI;EAEtB,eAAQ;IAEJ,QAAQ,EAAE,QAAQ;IAClB,WAAW,EAAE,IAAI;IAEjB,oBAAI;MACA,KAAK,EAAE,IAAI;MACX,WAAW,EAAE,IAAI;MACjB,KAAK,EAAE,KAAK;MACZ,MAAM,EAAE,IAAI;MACZ,WAAW,EAAE,QAAQ;MACrB,gBAAgB,EAAE,uBAAuB;MACzC,iBAAiB,EAAE,SAAS;MAC5B,eAAe,EAAE,OAAO;MACxB,mBAAmB,EAAE,OAAO;IAGhC,yBAAS;MACL,KAAK,EAAE,IAAI;MACX,WAAW,EAAE,IAAI;MAGjB,8BAAI;QACA,KAAK,EAAE,KAAK;QAGZ,mCAAK;UAED,KAAK,EAAE,KAAK;UAEZ,UAAU,EAAE,MAAM;UAElB,sDAAqB;YACjB,gBAAgB,EAAE,8BAA8B;UAGpD,sDAAqB;YACjB,gBAAgB,EAAE,6BAA6B;UAGnD,sDAAqB;YACjB,gBAAgB,EAAE,kCAAkC;UAIpD,6CAAI;YACA,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;YACZ,WAAW,EAAE,QAAQ;YACrB,eAAe,EAAE,KAAK;YACtB,iBAAiB,EAAE,SAAS;YAC5B,mBAAmB,EAAE,OAAO;UAGhC,6CAAI;YACA,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,GAAG;YACf,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,GAAG;YAChB,WAAW,EAAE,KAAK;YAClB,KAAK,EAAE,IAAI;YAEX,kDAAI;cACA,KAAK,EAAE,OAAO;YAIlB,0DAAe;cACX,WAAW,EAAE,GAAG;YAGpB,0DAAe;cACX,KAAK,EAAE,OAAO;YAElB,iDAAG;cACC,SAAS,EAAE,IAAI;cACf,KAAK,EAAE,OAAO;cAEd,uDAAQ;gBACJ,eAAe,EAAE,SAAS;IActD,yBAAS;MACL,KAAK,EAAE,IAAI;MACX,UAAU,EAAE,GAAG;MACf,WAAW,EAAE,IAAI;MACjB,KAAK,EAAE,KAAK;MAGZ,8BAAI;QACA,KAAK,EAAE,KAAK;QAGZ,mCAAK;UAED,KAAK,EAAE,KAAK;UAEZ,UAAU,EAAE,MAAM;UAElB,sDAAqB;YACjB,gBAAgB,EAAE,8BAA8B;UAGpD,sDAAqB;YACjB,gBAAgB,EAAE,6BAA6B;UAGnD,sDAAqB;YACjB,gBAAgB,EAAE,kCAAkC;UAIpD,6CAAI;YACA,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,IAAI;YACX,MAAM,EAAE,IAAI;YACZ,WAAW,EAAE,QAAQ;YACrB,eAAe,EAAE,KAAK;YACtB,iBAAiB,EAAE,SAAS;YAC5B,mBAAmB,EAAE,OAAO;UAGhC,6CAAI;YACA,UAAU,EAAE,IAAI;YAChB,UAAU,EAAE,GAAG;YACf,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,GAAG;YAChB,WAAW,EAAE,KAAK;YAClB,KAAK,EAAE,IAAI;YAEX,0DAAe;cACX,WAAW,EAAE,GAAG;YAGpB,0DAAe;cACX,KAAK,EAAE,OAAO;YAElB,iDAAG;cACC,SAAS,EAAE,IAAI;cACf,KAAK,EAAE,OAAO;cAEd,uDAAQ;gBACJ,eAAe,EAAE,SAAS;IAatD,wBAAQ;MACJ,KAAK,EAAE,KAAK;MACZ,UAAU,EAAE,GAAG;MACf,KAAK,EAAE,KAAK;MAKR,kCAAI;QACA,KAAK,EAAE,IAAI;QACX,YAAY,EAAE,GAAG;QACjB,aAAa,EAAE,IAAI;QACnB,gBAAgB,EAAE,0BAA0B;QAC5C,iBAAiB,EAAE,SAAS;QAC5B,mBAAmB,EAAE,QAAQ;QAI7B,6CAAa;UACT,YAAY,EAAE,IAAI;UAClB,gBAAgB,EAAE,IAAI;QAG1B,sCAAG;UAEC,SAAS,EAAE,IAAI;UACf,KAAK,EAAE,IAAI;IAS3B,4BAAY;MACR,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,KAAK;MACV,KAAK,EAAE,MAAM;MACb,SAAS,EAAE,gBAAgB;MAC3B,KAAK,EAAE,KAAK;MACZ,SAAS,EAAE,IAAI;MACf,cAAc,EAAE,GAAG;MACnB,KAAK,EAAE,IAAI;IAIf,qBAAQ;MACJ,QAAQ,EAAE,QAAQ;MAClB,GAAG,EAAE,IAAI;MACT,IAAI,EAAE,KAAK;MACX,SAAS,EAAE,gBAAgB;MAC3B,KAAK,EAAE,GAAG;MACV,MAAM,EAAE,KAAK;MACb,gBAAgB,EAAE,OAAO;MACzB,OAAO,EAAE,EAAE;;AAQtB,oCAAqC;EAAC,oBAAoB;EACtD,MAAO;IACJ,KAAK,EAAE,IAAI;IACX,MAAM,EAAE,IAAI;IACZ,gBAAgB,EAAE,IAAI;IAEtB,eAAQ;MAEJ,QAAQ,EAAE,QAAQ;MAClB,WAAW,EAAE,IAAI;MAEjB,oBAAI;QACA,KAAK,EAAE,OAAO;QAEd,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE,KAAK;QACZ,MAAM,EAAE,IAAI;QACZ,WAAW,EAAE,QAAQ;QACrB,gBAAgB,EAAE,uBAAuB;QACzC,iBAAiB,EAAE,SAAS;QAC5B,eAAe,EAAE,OAAO;QACxB,mBAAmB,EAAE,OAAO;MAGhC,yBAAS;QACL,KAAK,EAAE,OAAO;QAEd,MAAM,EAAE,MAAM;QACd,KAAK,EAAE,IAAI;QAGX,8BAAI;UACA,KAAK,EAAE,IAAI;UAGX,mCAAK;YAED,KAAK,EAAE,IAAI;YAiBP,6CAAI;cACA,OAAO,EAAE,IAAI;cACb,MAAM,EAAE,MAAM;cACd,KAAK,EAAE,IAAI;cACX,MAAM,EAAE,IAAI;cACZ,WAAW,EAAE,QAAQ;cACrB,eAAe,EAAE,KAAK;cACtB,iBAAiB,EAAE,SAAS;cAC5B,mBAAmB,EAAE,OAAO;YAGhC,6CAAI;cACA,YAAY,EAAE,IAAI;cAClB,UAAU,EAAE,IAAI;cAChB,UAAU,EAAE,GAAG;cACf,SAAS,EAAE,IAAI;cACf,WAAW,EAAE,GAAG;cAChB,WAAW,EAAE,KAAK;cAClB,KAAK,EAAE,IAAI;cAEX,kDAAI;gBACA,KAAK,EAAE,OAAO;cAIlB,0DAAe;gBACX,WAAW,EAAE,GAAG;cAGpB,0DAAe;gBACX,KAAK,EAAE,OAAO;cAElB,iDAAG;gBACC,SAAS,EAAE,IAAI;gBACf,KAAK,EAAE,OAAO;gBAEd,uDAAQ;kBACJ,eAAe,EAAE,IAAI;MAcjD,yBAAS;QACL,UAAU,EAAE,cAAc;QAC1B,KAAK,EAAE,OAAO;QAGd,MAAM,EAAE,SAAS;QACjB,KAAK,EAAE,IAAI;QAGX,8BAAI;UACA,KAAK,EAAE,IAAI;UAGX,mCAAK;YAED,KAAK,EAAE,IAAI;YAEX,UAAU,EAAE,MAAM;YAElB,sDAAqB;cACjB,gBAAgB,EAAE,8BAA8B;YAGpD,sDAAqB;cACjB,gBAAgB,EAAE,6BAA6B;YAGnD,sDAAqB;cACjB,gBAAgB,EAAE,kCAAkC;YAIpD,6CAAI;cACA,OAAO,EAAE,IAAI;YAIjB,6CAAI;cACA,YAAY,EAAE,IAAI;cAClB,UAAU,EAAE,IAAI;cAChB,UAAU,EAAE,GAAG;cACf,SAAS,EAAE,IAAI;cACf,WAAW,EAAE,GAAG;cAChB,WAAW,EAAE,KAAK;cAClB,KAAK,EAAE,IAAI;cAEX,0DAAe;gBACX,WAAW,EAAE,GAAG;cAGpB,0DAAe;gBACX,KAAK,EAAE,OAAO;cAElB,iDAAG;gBACC,SAAS,EAAE,IAAI;gBACf,KAAK,EAAE,OAAO;gBAEd,uDAAQ;kBACJ,eAAe,EAAE,SAAS;MAatD,wBAAQ;QACJ,QAAQ,EAAE,QAAQ;QAClB,GAAG,EAAE,IAAI;QACT,KAAK,EAAE,OAAO;QACd,UAAU,EAAE,GAAG;QACf,KAAK,EAAE,IAAI;QAKP,kCAAI;UACA,KAAK,EAAE,IAAI;UACX,UAAU,EAAE,MAAM;UAClB,KAAK,EAAE,OAAO;UACd,YAAY,EAAE,GAAG;UACjB,aAAa,EAAE,GAAG;UAClB,gBAAgB,EAAE,IAAI;UACtB,iBAAiB,EAAE,SAAS;UAC5B,mBAAmB,EAAE,QAAQ;UAC7B,UAAU,EAAE,cAAc;UAI1B,6CAAa;YACT,YAAY,EAAE,IAAI;YAClB,gBAAgB,EAAE,IAAI;YACtB,aAAa,EAAE,cAAc;UAGjC,sCAAG;YACC,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,IAAI;YACZ,WAAW,EAAE,IAAI;YACjB,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,IAAI;MAU3B,4BAAY;QACR,UAAU,EAAE,cAAe;QAC3B,QAAQ,EAAE,MAAM;QAChB,OAAO,EAAE,MAAM;QACf,GAAG,EAAE,IAAI;QACT,KAAK,EAAE,GAAG;QACV,SAAS,EAAE,aAAa;QACxB,KAAK,EAAE,IAAI;QACX,SAAS,EAAE,IAAI;QACf,cAAc,EAAE,GAAG;QACnB,UAAU,EAAE,MAAM;QAClB,KAAK,EAAE,IAAI;MAKf,qBAAQ;QACJ,OAAO,EAAE,IAAI;AAY5B,oBAOC;EANE,EAAG;IACA,MAAM,EAAG,IAAI;EAEhB,IAAK;IACF,MAAM,EAAG,IAAI", +"sources": ["common.scss"], +"names": [], +"file": "common.css" +} \ No newline at end of file diff --git a/eng/css/common.scss b/eng/css/common.scss new file mode 100644 index 0000000..01a7a61 --- /dev/null +++ b/eng/css/common.scss @@ -0,0 +1,2754 @@ +$point-color : #263d78; +$point-color2 : #ffc700; + +.clearfix { + *zoom : 1; + + &:after { + display: block; + clear: both; + content: ''; + }//end of clearfix:after +}//end of clearfix + +.sr_only { + position: absolute; + left: -99999px; +}//end of sr_only + +.inner { + width: 1200px; + margin: 0 auto; +}//end of inner + +@media screen and (max-width : 768px) { + .inner { + width: 100%; + //margin: 0 auto; + }//end of inner +}//end of 768px inner + + +#wrap { + width: 100%; + background-color: #f1f1f1; + +}//end of #wrap + +.upArrow { + display: none; + position: fixed; + bottom : 50px; + right : 50px; + width: 40px; + height: 40px; + background-color: $point-color; + border-radius: 50px; + cursor: pointer; + z-index: 9000; + + &:after { + position: absolute; + top: 7px; + left: 50%; + transform: translateX(-50%); + width: 22px; + height: 22px; + background-image: url(../images/up_arrow.png); + background-position: 50% 50%; + content: ''; + }//end of :after + + +}//end of upArrow + +body { + overflow-x: hidden; +}//end of body + +h3 { + font-size: 30px; + +} + + + + +::-webkit-scrollbar { + width: 8px; + height: 8px; + border: 3px solid #fff; +} +::-webkit-scrollbar-button:start:decrement, +:-webkit-scrollbar-button:end:increment { + display: block; + height: 10px; + background: url('./images/bg.png') #efefef; +} +::-webkit-scrollbar-track {background: #efefef; + -webkit-border-radius: 10px; + border-radius:10px; + -webkit-box-shadow: inset 0 0 4px rgba(0,0,0,.2); +} +::-webkit-scrollbar-thumb { + height: 50px; + width: 50px; + background: rgba(0,0,0,.2); + -webkit-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: inset 0 0 4px rgba(0,0,0,.1); +} + + +/*------- standard set -----------*/ + + +header { + position: fixed; + top: 0; + width: 100%; + height: 70px; + background-color: rgba(000,000,000,0.3); + // background-color: rgba(35, 129, 227, 0.8); + z-index: 99999; + transition: .3s; + + >.inner { + position: relative; + //background-color: pink; + + >.toggle { + display: none; + position: absolute; + top: 0; + right: 0; + width: 70px; + height: 70px; + cursor: pointer; + text-indent: -99999px; + background-image: url(../images/toggle.png); + }//end of toogle + + >h1 { + position: absolute; + width: 200px; + height: 70px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: 50%; + + + >a { + display: block; + width: 100%; + height: 100%; + } + + }//end of h1 + + >.gnb { + position: absolute; + right: 0; + width: 500px; + + + >ul { + >li { + float: left; + width: 100px; + //background-color: red; + + + >a { + display: block; + height: 70px; + font-size: 15px; + font-weight: 600; + color: rgba(255,255,255,0.6); + line-height: 70px; + text-align: center; + + &.on { + color: rgba(255,255,255,1); + } + + &:hover { + color: rgba(255,255,255,1); + } + + + + + + }//end of a + + >.sub { + position: absolute; + bottom: -40px; + width: 100%; + //background-color: red; + z-index: 5000; + display: none; + + &.sub01 { + + position: absolute; + left: 0; + //background-color: red; + + >.subcontainer >ul { + margin-left: 30px; + > li { + margin-left: 20px; + }//end of li + }//end of ul + + } + &.sub02 { + + position: absolute; + left: 0; + //background-color: orange; + + >.subcontainer >ul > li { + margin-left: 20px; + }//end of li + } + &.sub03 { + + position: absolute; + left: 0; + //background-color: lightblue; + + >.subcontainer >ul > li { + margin-left: 70px; + }//end of li + } + &.sub04 { + + position: absolute; + left: 0; + //background-color: green; + + >.subcontainer >ul { + margin-left: 300px; + + > li { + margin-left: 20px; + }//end of li + }//end of ul + } + + >.subcontainer { + //background-color: rgba(0,0,0,0.5); + + + >ul >li { + height: 40px; + line-height: 40px; + float: left; + font-size: 16px; + margin-left: 20px; + + >a { + display: block; + font-weight: 600; + color: #333; + + &:hover { + color: $point-color2; + } + } + + }//end of ul li + }//end of subcontainer + + }//end of sub + + }//end of li + }//end of ul + + .lang { + position: absolute; + top: 0; + right: 5px; + width: 80px; + height: 70px; + text-align: center; + line-height: 70px; + color: rgba(255,255,255,0.7); + font-weight: 600; + cursor: pointer; + // background-color: green; + + &:hover { color: rgba(255,255,255,1)} + + >ul { + display: none; + width: 100%; + background-color: rgba(000,000,000,0.5); + + >li { + line-height: 40px; + + &:hover a { + color: $point-color2; + } + &.on a { + color: $point-color2; + } + >a { + color: #fff; + } + } + } + + }//end of lang + }//end of gnb + }//end of inner + >.sub_bg { + display: none; + position: absolute; + top: 70px; + width: 100%; + height: 40px; + background-color: rgba(255, 255, 255, 1); + border-bottom: 1px solid #eee; + } +}//end of header + + + + +@media screen and (max-width : 768px) {/*header 반응형*/ + body::-webkit-scrollbar {display: none;}//추가 + + header { + position: fixed; + top: 0; + width: 100%; + height: 70px; + background-color: #444;//변경 + // background-color: rgba(35, 129, 227, 0.8); + z-index: 99999; + //transition: .3s; 제 + + >.inner { + position: relative; + //background-color: pink; + + >.toggle { + display: block; + position: absolute; + top: 0; + right: 0; + width: 70px; + height: 70px; + cursor: pointer; + text-indent: -99999px; + background-image: url(../images/toggle.png); + + &.clse { + background-image: url(../images/toggle_cls.png); + }//end of clse + }//end of toogle + + + + >h1 { + position: absolute; + width: 200px; + height: 70px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-position: 20% 50%;//변경 + background-size: 50%; + + + >a { + display: block; + width: 100%; + height: 100%; + } + + }//end of h1 + + >.gnb { + display: none;//토글키 + position: absolute; + top : 69px;//추가 + right: 0; + width: 100%;//변경 + background-color: #444; + + + >ul { + >li { + float: inherit;//변경 + width: 100%;//변경 + //background-color: red; + + + >a { + display: block; + width: 100%; + height: 70px; + font-size: 15px; + font-weight: 600; + color: rgba(255,255,255,0.6); + line-height: 70px; + padding-left: 30px;//추가 + text-align: left;//변경 + // background-color: green; + + &.on { + color: rgba(255,255,255,1); + } + + &:hover { + color: rgba(255,255,255,1); + } + + }//end of a + + >.sub { + position: inherit;//변경 + top: 0; + width: 100%; + background-color: #f1f1f1;//변경 + z-index: 5000; + display: none; + + &.sub01 { + + position: inherit;//변경 + left: 0; + //background-color: red; + + >.subcontainer >ul { + margin-left: 0px;//변경 + > li { + margin-left: 0px;//변경 + padding-left: 35px;//추가 + }//end of li + }//end of ul + + } + &.sub02 { + + position: inherit;//변경 + left: 0; + //background-color: orange; + + >.subcontainer >ul > li { + margin-left: 0px;//변경 + padding-left: 35px;//추가 + }//end of li + } + &.sub03 { + + position: inherit;//변경 + left: 0; + //background-color: lightblue; + + >.subcontainer >ul > li { + margin-left: 0px;//변경 + }//end of li + } + &.sub04 { + + position: inherit;//변경 + left: 0; + //background-color: green; + + >.subcontainer >ul { + margin-left: 0px;//변경 + padding-left: 35px;//추가 + + > li { + margin-left: 0px;//변경 + }//end of li + }//end of ul + } + + >.subcontainer { + //background-color: rgba(0,0,0,0.5); + + + >ul >li { + height: 60px;//변경 + line-height: 60px;//변경 + float: inherit; + font-size: 16px; + margin-left: 0px;//변경 + border-bottom : 1px solid #ccc;//추가 + + &:last-child { + border-bottom: none; + } + + >a { + display: block; + font-weight: 600; + color: #333; + + &:hover { + color: $point-color2; + } + } + + }//end of ul li + }//end of subcontainer + + }//end of sub + + }//end of li + }//end of ul + + .lang { + display: block; + position: absolute; + top: -60px; + right: 80px;//변경 + width: 60px; + height: 50px; + text-align: center; + line-height: 50px; + color: rgba(255,255,255,0.7); + font-size: 13px; + font-weight: 600; + cursor: pointer; + //background-color: #444; + border-radius: 14px; + + &:hover { color: rgba(255,255,255,1)} + + >ul { + margin-top: 10px; + display: none; + width: 100%; + background-color: rgba(000,000,000,0.5); + + >li { + line-height: 50px; + + &:hover a { + color: $point-color2; + } + &.on a { + color: $point-color2; + } + >a { + color: #fff; + } + } + } + + }//end of lang + }//end of gnb + }//end of inner + >.sub_bg { + display: none; + position: absolute; + top: 70px; + width: 100%; + height: 40px; + background-color: rgba(255, 255, 255, 1); + border-bottom: 1px solid #eee; + } + }//end of header +}//end of 768px header + +#mVisual { + position: relative; + overflow: hidden; + width: 100%; + height: 100vh; + + >.mVisual_img { + width: 100%; + height: 100%; + z-index: -1; + + >ul { + >li { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-indent: -99999px; + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; + + &:nth-child(1) { + background-image: url(../images/img01.jpg); + + + }//end of li:nth-child(1) + + &:nth-child(2) { + background-image: url(../images/mVisual02.jpg); + background-position: 50% 80%; + + }//end of li:nth-child(1) + + &:nth-child(3) { + background-image: url(../images/mVisual08.jpg); + //background-position: 100% 0; + + }//end of li:nth-child(1) + + &:nth-child(4) { + background-image: url(../images/mVisual04.jpg); + + }//end of li:nth-child(1) + + }//end of li + }//end of ul + }//end of mVisual_img + + >.mVisual_txt { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 600px; + height: 200px; + background-color: rgba(0, 0, 0, 0.6); + transition: .5s; + z-index: 5000; + + >ul { + //padding-top: -200px; + + >li { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 100%; + transform: translate(-50%, -30%); + height: 100%; + text-align: center; + + >dl { + + >dt { + position: relative; + margin-bottom: 25px; + font-size: 35px; + font-weight: 600; + color: #fff; + + &:after { + position: absolute; + bottom: -15px; + left: 50%; + transform: translateX(-50%); + width: 120px; + height: 3px; + background-color: $point-color2; + content: ''; + }//end of dt :after + }//end of dt + + >dd { + letter-spacing: 2px; + line-height: 1.4em; + font-size: 16px; + color: #fff; + }//end of dd + }//end of dl + + }//end of li + }//end of ul + }//end of mVisual_txt + + >.mVisual_indicator { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 600px; + height: 200px; + z-index: 6000; + + &:after { + position: absolute; + bottom: 24px; + right: 54px; + width: 6px; + height: 6px; + background-color: $point-color2; + border-radius: 5px; + content: ''; + }//end of mVisual_indicator:after (dot) + + + >p { + display: block; + position: absolute; + bottom: 20px; + width: 17px; + height: 15px; + text-indent: -99999px; + transition: .4s; + + cursor: pointer; + background-repeat: no-repeat; + background-size: cover; + + &.mVisual_prev_btn { + background-image: url(../images/prev_btn.png); + right:80px; + + &:hover { + background-image: url(../images/prev_btn_hover.png); + }//end of hover + }//end of prev + + &.mVisual_next_btn { + background-image: url(../images/next_btn.png); + right: 20px; + + &:hover { + background-image: url(../images/next_btn_hover.png); + }//end of hover + + }//end of prev + }//end of p + }//end of mVisual_indicator + + >.downArrow { + position: absolute; + bottom: 20px; + left: 50%; + transform: translateX(-50%) rotate(90deg); + width: 50px; + height: 50px; + cursor: pointer; + background-image: url(../images/next_btn.png); + background-repeat: no-repeat; + background-position: 50% 50%; + animation: downArrow .9s infinite ; + + }//end of downArrow +}//end of #mVisual + + + +@media screen and (max-width : 768px) {/*mVisual 반응형*/ + #mVisual { + position: relative; + overflow: hidden; + width: 100%; + height: 100vh; + + >.mVisual_img { + width: 100%; + height: 100%; + z-index: -1; + + >ul { + >li { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + text-indent: -99999px; + background-repeat: no-repeat; + background-size: cover; + background-position: 50% 50%; + + &:nth-child(1) { + background-image: url(../images/img01.jpg); + + + }//end of li:nth-child(1) + + &:nth-child(2) { + background-image: url(../images/mVisual02.jpg); + background-position: 50% 80%; + + }//end of li:nth-child(1) + + &:nth-child(3) { + background-image: url(../images/mVisual08.jpg); + //background-position: 100% 0; + + }//end of li:nth-child(1) + + &:nth-child(4) { + background-image: url(../images/mVisual04.jpg); + + }//end of li:nth-child(1) + + }//end of li + }//end of ul + }//end of mVisual_img + + >.mVisual_txt { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 100%;//변경 + height: 200px; + background-color: rgba(0, 0, 0, 0.6); + transition: .5s; + z-index: 5000; + + >ul { + //padding-top: -200px; + + >li { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 100%; + transform: translate(-50%, -30%); + height: 100%; + text-align: center; + + >dl { + + >dt { + position: relative; + margin-bottom: 25px; + font-size: 35px; + font-weight: 600; + color: #fff; + + &:after { + position: absolute; + bottom: -15px; + left: 50%; + transform: translateX(-50%); + width: 120px; + height: 3px; + background-color: $point-color2; + content: ''; + }//end of dt :after + }//end of dt + + >dd { + letter-spacing: 2px; + line-height: 1.4em; + font-size: 16px; + color: #fff; + }//end of dd + }//end of dl + + }//end of li + }//end of ul + }//end of mVisual_txt + + >.mVisual_indicator { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 600px; + height: 200px; + z-index: 6000; + + &:after { + position: absolute; + bottom: 28px; + left: 50%;//변경 + transform: translateX(-50%); + width: 6px; + height: 6px; + background-color: $point-color2; + border-radius: 5px; + content: ''; + }//end of mVisual_indicator:after (dot) + + + >p { + display: block; + position: absolute; + bottom: 20px; + width: 100px; + height: 23px; + text-indent: -99999px; + transition: .4s; + + cursor: pointer; + background-repeat: no-repeat; + background-size: contain; + + &.mVisual_prev_btn { + background-image: url(../images/prev_btn.png); + background-position: 100% 50%; + left: 30%; + + &:hover { + background-image: url(../images/prev_btn_hover.png); + }//end of hover + }//end of prev + + &.mVisual_next_btn { + background-image: url(../images/next_btn.png); + left: 53%; + + &:hover { + background-image: url(../images/next_btn_hover.png); + }//end of hover + + }//end of prev + }//end of p + }//end of mVisual_indicator + + >.downArrow { + position: absolute; + bottom: 20px; + left: 50%; + transform: translateX(-50%) rotate(90deg); + width: 50px; + height: 50px; + cursor: pointer; + background-image: url(../images/next_btn.png); + background-repeat: no-repeat; + background-position: 50% 50%; + animation: downArrow .9s infinite ; + + }//end of downArrow + }//end of #mVisual +}//end of 768px #mVisual + + + + + + +#company { + position: relative; + width: 100%; + + + >.inner { + + >h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #222; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -20px; + left: 50%; + transform: translateX(-50%); + font-size: 13px; + font-weight: 800; + color: $point-color; + letter-spacing: -0.5px; + content: "company Status"; + }//end of :after + }//end of h3 + + + >.company_img { + //float: left; + width: 100%; + height: 450px; + margin: 45px 0 50px; + background-image: url(../images/intro.png); + background-position: 45% 50%; + background-size: contain; + background-repeat: no-repeat; + //background-color: rgba(190, 116, 15, 0.76) + }//end of company_img + + >.company_intro { + + margin : 50px 0 50px; + text-align: left; + font-size: 16px; + font-weight: 500; + line-height: 1.9em; + + + >.company_l { + position: relative; + float: left; + width: 600px; + margin-top: -10px; + text-align: right; + + &:after { + position: absolute; + top: 10px; + right : 0; + width: 2px; + height: 222px; + background-color: #e5e5e5; + content: ''; + } + + >ul { + padding-right: 30px; + + >li { + + >dl{ + >dt { + font-size: 20px; + margin-bottom: 7px; + color: rgb(108, 108, 108); + } + >dd { + font-size: 30px; + font-weight: 900; + color: $point-color; + + } + } + + }//end of li + }//end of ul + + >ol { + font-size: 22px; + margin-top: 40px; + padding-right: 30px; + font-weight: 600; + + >li { + line-height: 2em; + >dl { + >dd { + >em { + color: #eeba01; + } + } + } + } + }//end of ol + + + }//end of company_l + + >.company_r { + float: left; + width: 600px; + text-align: left; + + >ul { + padding-left: 30px; + height: 260px; + //background-color: red; + + >li { + margin-bottom: 5px; + width: 200px; + background-color: $point-color; + //border-radius: 6px; + transition: .2s; + height: 40px; + + >a { + display: block; + padding-left: 15px; + font-weight: 500; + font-size: 15px; + letter-spacing: px; + line-height: 38px; + height: 42px; + color: #fff; + transition: .2s; + }//end of a + + &:hover { + background-color: $point-color2; + //background-color: #f1f1f1; + //border: 1px solid $point-color; + //box-sizing: border-box; + // border-radius: 6px; + + } + + &:hover a { + color: #f1f1f1; + // color: $point-color; + //font-size: 18PX; + //font-weight: 600; + } + }//end of li + }//end of ul + + }//end of company_l + + + }//end of company_intro + + /* >.company_info { + //float: left; + width: 600px; + height: 500px; + margin-top: 45px; + //background-color: red; + + >ul { + margin : 50px 0 0 10px; + >li { + margin-top : 20px; + font-size: 20px; + font-weight: 600; + letter-spacing: 0px; + color: #333; + + >em { + color: #fc4040; + }//end of em + + &:nth-child(5) { + line-height: 1.5em; + }//end of li:nth-child(5) + + >dl { + >dt { + margin-top: 40px; + font-size: 25px; + color: #aaa; + }//end of dt + >dd { + margin-top: 10px; + font-size: 14px; + font-weight: 500; + color: #bbb; + letter-spacing: 0px; + line-height: 1.7em; + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of company_info + + */ + }//end of inner +}//end of #company + +@media screen and(max-width : 768px) {/*company 반응형*/ + #company { + position: relative; + width: 100%; + + + >.inner { + + >h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #222; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -20px; + left: 50%; + transform: translateX(-50%); + font-size: 13px; + font-weight: 800; + color: $point-color; + letter-spacing: -0.5px; + content: "company Status"; + }//end of :after + }//end of h3 + + + >.company_img { + display: none;//추가 + //float: left; + width: 100%; + height: 450px; + margin: 45px 0 50px; + background-image: url(../images/intro.png); + background-position: 45% 50%; + background-size: contain; + background-repeat: no-repeat; + //background-color: rgba(190, 116, 15, 0.76) + }//end of company_img + + >.company_intro { + width: 100%;//추가 + margin : 50px 0 50px; + text-align: center; + font-size: 16px; + font-weight: 500; + line-height: 1.9em; + + + >.company_l { + position: relative; + float: inherit;//변경 + width: 100%;//변경 + margin-top: 0px;//변경 + padding-top: 30px;//추가 + text-align: center; + + &:after { + display: none;//막대기 제거 + position: absolute; + top: 10px; + right : 0; + width: 2px; + height: 222px; + background-color: #e5e5e5; + content: ''; + } + + >ul { + padding-right: 0px;//변경 + + >li { + + >dl{ + >dt { + font-size: 20px; + margin-bottom: 7px; + color: rgb(108, 108, 108); + } + >dd { + font-size: 30px; + font-weight: 900; + color: $point-color; + + } + } + + }//end of li + }//end of ul + + >ol { + font-size: 16px; + margin-top: 20px;//변경 + //padding-right: 0px;//변경 + padding: 0 5px; + font-weight: 500;//변경 + + >li { + line-height: 1.45em;//변경 + >dl { + >dd { + >em { + color: #eeba01; + } + } + } + } + }//end of ol + + + }//end of company_l + + >.company_r { + float: inherit;//변경 + width: 100%; + padding-top: 40px; + text-align: center; + + >ul { + padding-left: 0px;//변경 + height: auto;//변경 + //background-color: red; + + >li { + margin: 0 auto 5px;//추가 + //margin-bottom: 5px; + width: 90%;//변경 + background-color: $point-color; + //border-radius: 6px; + transition: .2s; + height: 50px; + + >a { + display: block; + padding-left: 15px; + font-weight: 500; + font-size: 17px; + letter-spacing: 1px; + line-height: 50px; + height: 50px; + color: #fff; + transition: .2s; + }//end of a + + &:hover { + background-color: $point-color2; + //background-color: #f1f1f1; + //border: 1px solid $point-color; + //box-sizing: border-box; + // border-radius: 6px; + + } + + &:hover a { + color: #f1f1f1; + // color: $point-color; + //font-size: 18PX; + //font-weight: 600; + } + }//end of li + }//end of ul + + }//end of company_l + + + }//end of company_intro + }//end of inner + }//end of #company + +}//company 반응형 + +#service { + margin-top: 20px; + width: 100%; + height: 600px; + //background-image: url(../images/one.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 70%; + //background-color: #d6b179;/*#71a8bc*//*ffb636*/ + + >.inner { + position: relative;/*indicator position*/ + + + >h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #333; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -20px; + left: 50%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: $point-color; + letter-spacing: 0px; + content: "BUSINESS AREA"; + }//end of :after + }//end of h3 + + >.service_box { + position: relative;/*service_container position*/ + overflow: hidden; + width: 1200px; + height: 402px; + margin: 50px auto 0; + //background-color: green; + + >.service_container { + position: absolute; + top: 1px; + left: 0; + width: 5000px; + + >div { + float: left; + width: 1200px; + height: 100%; + + >ul { + width: 1200px; + margin: 0 auto; + //background-color: lightblue; + + >li { + //cursor: pointer; + position: relative; + float: left; + margin-left: 20px; + width: 275px; + height: 370px; + transition: .5s; + background-color: #fff; + border-radius: 5px; + //outline: 1px solid #555; + //background-color: pink; + + &:after { + opacity: 0; + position: absolute; + top: 2.5px; + left: 5px; + width: 260px; + height: 360px; + border: 2px solid $point-color; + transition: .3s; + content: ''; + } + + + + &:hover:after {opacity: 1;} + + + + >dl { + >dt { + margin: 50px auto 0px; + width: 120px; + height: 120px; + //background-image: url(../images/service_bg.png); + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + transition: .4s; + //background-color: green; + + >p { + display: block; + text-indent: -99999px; + margin: 0px auto; + padding-top: 40px; + width: 90px; + height: 90px; + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + transition: .6s; + }//end of p + }//end of dt + + >.topic { + margin: 0px 0; + width: 100%; + height: 33px; + font-size: 18px; + font-weight: 700; + text-align: center; + line-height: 30px; + transition: .6s; + color: #222; + //background-color: gray; + }//end of topic + + >.info { + width: 100%; + min-height: 100px; + line-height: 1.6em; + letter-spacing: -1px; + font-size: 13px; + font-weight: 500; + text-align: center; + transition: .6s; + color: #aaa; + //background-color: orange; + }//end of info + + >.more { + + display: block; + width: 150px; + margin: 5px auto 0; + text-align: center; + font-weight: 600; + color: $point-color2; + z-index: 4000; + + >em { + color: $point-color; + } + + >a { + position: absolute; + top: 0; + left: 0; + display: block; + width: 275px; + height: 370px; + color: #fff; + //background-color: rgba(0,0,0,0.5); + z-index: 7000; + } + }//end of more + + }//end of dl + + }//end of li + }//end of ul + }//end of div style + + >.service_1 { + //background-color: red; + >ul >li{ + &:nth-child(1) p {background-image: url(../images/icon_4.png);} + &:nth-child(2) p {background-image: url(../images/icon_2.png);} + &:nth-child(3) p {background-image: url(../images/icon_1.png);} + &:nth-child(4) p {background-image: url(../images/icon_7.png);} + }//end of serivce_1 icon images + }//end of service_1 + + >.service_2 { + display: none; + //background-color: green; + + >ul >li { + background-size: 20%; + // &:nth-child(1) p {background-image: url(../images/icon_2.png);} + //&:nth-child(1) p {background-image: url(../images/icon_5.png);} + //&:last-child {display: none;} + } + }//end of service_2 + + + }//end of service_container + + + }//end of service_box + + >.service_indicator { + position: absolute; + bottom: -35px; + left: 50%; + transform: translateX(-50%); + width: 100px; + height: 20px; + //background-color: orange; + + >ul { + + >li { + float: left; + margin-left: 20px; + width: 20px; + height: 20px; + background-color: #333; + border-radius: 20px; + cursor: pointer; + + &.on { + background-color: #fff; + }//end of .on + }//end of li + }//end of ul + }//end of service_indicator + + >.service_RL_btn { + display: none; + position: absolute; + top: 50%; + width: 100%; + + >p { + position: absolute; + top: 0; + width: 40px; + height: 40px; + text-indent: -99999px; + //background-color: red; + cursor: pointer; + }//end of p + + >.prev { + position: absolute; + left: -20px; + + &:after { + position: absolute; + top: 25%; + left: -10px; + transform: rotate(-45deg); + width: 25px; + height: 2px; + background-color: $point-color; + content: ''; + }//prev + &:before { + position: absolute; + bottom: 25%; + left: -10px; + transform: rotate(45deg); + width: 25px; + height: 2px; + background-color: $point-color; + content: ''; + }//prev + }//end of prev + + >.next { + position: absolute; + right: -20px; + + &:after { + position: absolute; + top: 25%; + left: 25px; + transform: rotate(45deg); + width: 25px; + height: 2px; + background-color: $point-color; + content: ''; + } + &:before { + position: absolute; + bottom: 25%; + left: 25px; + transform: rotate(-45deg); + width: 25px; + height: 2px; + background-color: $point-color; + content: ''; + } + }//end of next + }//end of service_RL_btn + }//end of inner +}//end of service + +@media screen and (max-width : 768px) {/*service 768px 반응형*/ + #service { + margin-top: 20px; + width: 100%; + height: auto;//추가 + //background-image: url(../images/one.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 70%; + //background-color: #d6b179;/*#71a8bc*//*ffb636*/ + + >.inner { + position: relative;/*indicator position*/ + + + >h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #333; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -20px; + left: 50%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: $point-color; + letter-spacing: 0px; + content: "BUSINESS AREA"; + }//end of :after + }//end of h3 + + >.service_box { + position: relative;/*service_container position*/ + overflow: hidden; + width: 350px;//변경 + height: 402px; + margin: 50px auto;//변경 + //background-color: green; + + >.service_container { + position: absolute; + top: 1px; + left: 0; + width: 1400px; + + >div { + float: left; + width: 1400px; + height: 100%; + + >ul { + width: 1400px; + margin: 0 auto; + //background-color: lightblue; + + >li { + //cursor: pointer; + position: relative; + float: left; + margin-left: 0px; + width: 350px;//변경 + height: 370px; + transition: .5s; + background-color: #fff; + border-radius: 5px; + //outline: 1px solid #555; + //background-color: pink; + + &:after { + opacity: 0; + position: absolute; + top: 10px; + left: 10px; + width: 325px; + height: 345px; + border: 2px solid $point-color; + transition: .3s; + content: ''; + } + + + + &:hover:after {opacity: 1;} + + + + >dl { + >dt { + margin: 50px auto 0px; + width: 120px; + height: 120px; + //background-image: url(../images/service_bg.png); + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + transition: .4s; + //background-color: green; + + >p { + display: block; + text-indent: -99999px; + margin: 0px auto; + padding-top: 40px; + width: 90px; + height: 90px; + background-position: 50% 50%; + background-size: contain; + background-repeat: no-repeat; + transition: .6s; + }//end of p + }//end of dt + + >.topic { + margin: 0px 0; + width: 100%; + height: 33px; + font-size: 23px; + font-weight: 700; + text-align: center; + line-height: 30px; + transition: .6s; + color: #222; + //background-color: gray; + }//end of topic + + >.info { + width: 100%; + min-height: 100px; + line-height: 1.6em; + letter-spacing: -1px; + font-size: 15px; + font-weight: 500; + text-align: center; + transition: .6s; + color: #aaa; + //background-color: orange; + }//end of info + + >.more { + + display: block; + width: 150px; + margin: 5px auto 0; + text-align: center; + font-weight: 600; + color: $point-color2; + z-index: 4000; + + >em { + color: $point-color; + } + + >a { + position: absolute; + top: 0; + left: 0; + display: block; + width: 100%; + height: 370px; + color: #fff; + //background-color: rgba(0,0,0,0.5); + z-index: 7000; + } + }//end of more + + }//end of dl + + }//end of li + }//end of ul + }//end of div style + + >.service_1 { + //background-color: red; + >ul >li{ + &:nth-child(1) p {background-image: url(../images/icon_4.png);} + &:nth-child(2) p {background-image: url(../images/icon_2.png);} + &:nth-child(3) p {background-image: url(../images/icon_1.png);} + &:nth-child(4) p {background-image: url(../images/icon_7.png);} + }//end of serivce_1 icon images + }//end of service_1 + + >.service_2 { + display: none; + //background-color: green; + + >ul >li { + background-size: 20%; + // &:nth-child(1) p {background-image: url(../images/icon_2.png);} + //&:nth-child(1) p {background-image: url(../images/icon_5.png);} + //&:last-child {display: none;} + } + }//end of service_2 + + + }//end of service_container + + + }//end of service_box + + + + >.service_RL_btn { + display: block;//추가 + position: absolute; + top: 50%; + width: 100%; + + >p { + position: absolute; + top: -35px; + width: 60px; + height: 60px; + text-indent: -99999px; + z-index: 7000;//추가 + //background-color: red; + cursor: pointer; + }//end of p + + >.prev { + position: absolute; + left: 60px;//변경 + + &:after { + position: absolute; + top: 35%; + left: 20px;//변경 + transform: rotate(-45deg); + width: 25px; + height: 2px; + background-color: $point-color; + content: ''; + }//prev + &:before { + position: absolute; + bottom: 35%; + left: 20px;//변경 + transform: rotate(45deg); + width: 25px; + height: 2px; + background-color: $point-color; + content: ''; + }//prev + }//end of prev + >.next { + position: absolute; + right: 60px; + + &:after { + position: absolute; + top: 35%; + left: 15px;//변경 + transform: rotate(45deg); + width: 25px; + height: 2px; + background-color: $point-color; + content: ''; + } + &:before { + position: absolute; + bottom: 35%; + left: 15px;//변경 + transform: rotate(-45deg); + width: 25px; + height: 2px; + background-color: $point-color; + content: ''; + } + }//end of next + }//end of service_RL_btn + }//end of inner + }//end of service +}//service 768px 반응형 + +#company_m_info { + width: 100%; + height: 240px; + background-image: url(../images/bg_1.jpg); + background-attachment: fixed; + background-repeat: no-repeat; + background-position: 90% 50%; + background-size: cover; + + >.inner { + padding-top: 90px; + + >ul { + width: 100%; + height: 100px; + //background-color: pink; + + >li { + width: 300px; + float: left; + text-align: center; + color: #fff; + font-size: 20px; + //font-weight: 600; + + &:nth-child(1) { + margin-left: 150px; + } + + &:nth-child(2) { + position: relative; + + &:after { + position: absolute; + top: 50%; + left: 0; + width: 1px; + height: 15px; + background-color: #888; + content: ''; + } + + &:before { + position: absolute; + top: 50%; + right: 0; + width: 1px; + height: 15px; + background-color: #888; + content: ''; + } + + >dl>dt { + letter-spacing: -3px; + } + } + + + >dl { + + >dt { + font-size: 40px; + font-weight: 500; + color: $point-color2; + margin-bottom: 10px; + + >span { + font-size: 17px; + } + + }//end of dt + >dd { + font-size: 17px; + }//end of dd + } + }//end of li + }//end of ul + }//end of inner +}//end of company_m_info + +@media screen and(max-width : 768px) {/*company m info 768px 반응형*/ + #company_m_info { + display: none; + width: 100%; + height: 240px; + background-image: url(../images/bg_1.jpg); + background-attachment: fixed; + background-repeat: no-repeat; + background-position: 90% 50%; + background-size: cover; + + >.inner { + padding-top: 90px; + + >ul { + width: 100%; + height: 100px; + //background-color: pink; + + >li { + width: 300px; + float: left; + text-align: center; + color: #fff; + font-size: 20px; + //font-weight: 600; + + &:nth-child(1) { + margin-left: 150px; + } + + &:nth-child(2) { + position: relative; + + &:after { + position: absolute; + top: 50%; + left: 0; + width: 1px; + height: 15px; + background-color: #888; + content: ''; + } + + &:before { + position: absolute; + top: 50%; + right: 0; + width: 1px; + height: 15px; + background-color: #888; + content: ''; + } + + >dl>dt { + letter-spacing: -3px; + } + } + + + >dl { + + >dt { + font-size: 40px; + font-weight: 500; + color: $point-color2; + margin-bottom: 10px; + + >span { + font-size: 17px; + } + + }//end of dt + >dd { + font-size: 17px; + }//end of dd + } + }//end of li + }//end of ul + }//end of inner + }//end of company_m_info +}//company m info 768px 반응형 + + + + + +#contact { + width: 100%; + height: 750px; + background-color: $point-color; + + >h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #fff; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -20px; + left: 50.2%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #111; + letter-spacing: 4px; + content: "How to come"; + }//end of :after + }//end of h3 + + >.mapContainer { + width: 600px; + height: 300px; + margin: 60px auto 200px; + + >.map { + width : 600px; + height : 450px; + + background-image: url(../images/map_18.08.06.jpg); + background-position: 50% 50%; + background-size: cover; + border : 0; + + >a { + display: block; + width: 100%; + height: 100%; + text-indent: -99999px; + } + }//end of map + }//end of mapContainer + + >.mapInfo { + position: relative; + width: 100%; + text-align: center; + + &:after { + position: absolute; + top: 0; + left: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: 0 50%; + content: ''; + }//end of :after + + &:before { + position: absolute; + bottom: 0; + right: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: -35px 50%; + content: ''; + }//end of :after + + + >.inner { + >ul { + >li { + font-size: 18px; + font-weight: 600; + color: #fff; + line-height: 1.8em; + + >span { + color: #111; + font-weight: 900; + }//end of span + }//end of li + }//end of ul + }//end of inner + }//end of mapInfo + +}//end of #contact + + +@media screen and(max-width : 768px) {/*contact 768px 반응형*/ + + #contact { + width: 100%;//변경 + height: auto;//변경 + background-color: $point-color; + + >h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #fff; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -20px; + left: 50.2%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #111; + letter-spacing: 4px; + content: "How to come"; + }//end of :after + }//end of h3 + + >.mapContainer { + width: 90%;//변경 + height: 480px; + margin: 60px auto 40px; + + >.map { + width : 100%; + height : 450px; + + background-image: url(../images/map_18.08.06.jpg); + background-position: 10% 50%; + background-size: cover; + border : 0; + + >a { + display: block; + width: 100%; + height: 100%; + text-indent: -99999px; + } + }//end of map + }//end of mapContainer + + >.mapInfo { + position: relative; + width: 100%; + text-align: center; + padding-bottom: 50px;//추가 + + &:after { + display: none;//추가 + position: absolute; + top: 0; + left: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: 0 50%; + content: ''; + }//end of :after + + &:before { + display: none;//추가 + position: absolute; + bottom: 0; + right: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: -35px 50%; + content: ''; + }//end of :after + + + >.inner { + >ul { + >li { + font-size: 18px; + font-weight: 600; + color: #fff; + line-height: 1.8em; + + >span { + display: block; + color: #111; + font-weight: 900; + }//end of span + }//end of li + }//end of ul + }//end of inner + }//end of mapInfo + + }//end of #contact + +}//contact 768px 반응형 + +footer { + width: 100%; + height: 170px; + background-color: #333; + + >.inner { + //background-color: pink; + position: relative; + padding-top: 20px; + + >h1 { + float: left; + margin-left: 40px; + width: 120px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + }//end of h1 + + >.f_left { + float: left; + margin-left: 50px; + //background-color: pink; + + >ul { + width: 280px; + // background-color: red; + + > li { + + width: 320px; + //background-color: pink; + text-align: center; + + &:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + + }//end of dt + >dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; + + >em { + color: #909090; + } + + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: underline; + } + + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of f_left + + >address { + float: left; + margin-top: 0px; + margin-left: 30px; + width: 340px; + //background-color: green; + + >ul { + width: 350px; + // background-color: red; + + > li { + + width: 320px; + //background-color: pink; + text-align: center; + + &:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + + }//end of dt + >dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: underline; + } + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of address + + >.f_nav { + float: right; + margin-top: 0px; + width: 180px; + //background-color: blue; + + >ul { + + >li { + float: left; + margin-right: 9px; + padding-right: 11px; + background-image: url(../images/f_right.png); + background-repeat: no-repeat; + background-position: 100% 73%; + + + + &:last-child { + margin-right: none; + background-image: none; + } + + >a { + + font-size: 13px; + color: #fff; + + + } + } + } + + } + + >.copyright { + position: absolute; + top: 120px; + right: -140px; + transform: translateX(-50%); + width: 315px; + font-size: 13px; + letter-spacing: 1px; + color: #fff; + + }//end of copyright + + &:after { + position: absolute; + top: 30px; + left: 200px; + transform: translateX(-50%); + width: 1px; + height: 120px; + background-color: #808080; + content: ''; + }//end of inner:after 하단 1자 선(상호) + + + }//end of inner +}//end of footer + + +@media screen and(max-width : 768px) {/*footer 768px 반응형*/ + footer { + width: 100%; + height: auto; + background-color: #333; + + >.inner { + //background-color: pink; + position: relative; + padding-top: 20px; + + >h1 { + float: inherit; + //margin-left: 0px;제거 + margin: 0 auto 180px;//추가 + width: 120px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + }//end of h1 + + >.f_left { + float: inherit; + // margin-left: 50px; + margin: 0 auto; + width: 100%;//추가 + //background-color: pink; + + >ul { + width: 100%;//변경 + //background-color: red; + + > li { + + width: 100%;//변경 + //background-color: pink; + //text-align: center; + + &:nth-child(1) dl dt { + // background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + //background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + //background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + display: none; + margin: 0 auto; + width: 100%; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + + }//end of dt + >dd { + padding-left: 20px;//추가 + text-align: left;//변경 + margin-top: 8px; + font-size: 16px;//변경 + font-weight: 500; + line-height: 1.2em; + color: #fff; + + >em { + color: #909090; + } + + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: none;//변경 + } + + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of f_left + + >address { + border-top: 1px solid #666; + float: inherit;//변경 + // margin-top: 0px; + // margin-left: 30px; + margin: 10px auto; + width: 100%;//변경 + //background-color: green; + + >ul { + width: 100%; + // background-color: red; + + > li { + + width: 100%; + //background-color: pink; + text-align: center; + + &:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + display: none; + + + }//end of dt + >dd { + padding-left: 20px; + text-align: left;//변경 + margin-top: 6px;//변경 + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: underline; + } + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of address + + >.f_nav { + position: absolute; + top: 75px; + float: inherit;//변경 + margin-top: 0px; + width: 100%;//변경 + //background-color: blue; + + >ul { + + >li { + width: 100%;//추가 + text-align: center;//추가 + float: inherit;//변경 + margin-right: 0px;//변경 + padding-right: 0px;//변경 + background-image: none;//변경 + background-repeat: no-repeat; + background-position: 100% 73%; + border-top: 1px solid #666; + + + + &:last-child { + margin-right: none; + background-image: none; + border-bottom: 1px solid #666; + } + + >a { + display: block; + height: 50px; + line-height: 50px; + font-size: 16px; + color: #fff; + //background-color: orange; + + + } + } + } + + } + + >.copyright { + border-top: 1px solid #666 ;//추가 + position: static; + padding: 20px 0; + top: 10px;//변경 + right: 50%;//변경 + transform: translateX(0); + width: 100%; + font-size: 13px; + letter-spacing: 1px; + text-align: center; + color: #fff; + //background-color: green; + + }//end of copyright + + &:after { + display: none; + + }//end of inner:after 하단 1자 선(상호) + + + }//end of inner + }//end of footer + + +}//footer 768px 반응형 + + +@keyframes downArrow { + 0% { + bottom : 40px; + } + 100% { + bottom : 20px; + } +} diff --git a/eng/css/common_eng.css b/eng/css/common_eng.css new file mode 100644 index 0000000..0a6c53d --- /dev/null +++ b/eng/css/common_eng.css @@ -0,0 +1,1407 @@ +@charset "UTF-8"; +#contact { + width: 100%; + height: 750px; + background-color: #263d78; } + #contact > h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #fff; + text-transform: uppercase; } + #contact > h3:after { + position: absolute; + bottom: -20px; + left: 50.2%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #111; + letter-spacing: 4px; + content: "How to come"; } + #contact > .mapContainer { + width: 600px; + height: 300px; + margin: 60px auto 200px; } + #contact > .mapContainer > .map { + width: 600px; + height: 450px; + background-image: url(../images/map_eng_18.08.06.jpg); + background-position: 50% 50%; + background-size: cover; + border: 0; } + #contact > .mapContainer > .map > a { + display: block; + width: 100%; + height: 100%; + text-indent: -99999px; } + #contact > .mapInfo { + position: relative; + width: 100%; + text-align: center; } + #contact > .mapInfo:after { + position: absolute; + top: 0; + left: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: 0 50%; + content: ''; } + #contact > .mapInfo:before { + position: absolute; + bottom: 0; + right: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: -35px 50%; + content: ''; } + #contact > .mapInfo > .inner > ul > li { + font-size: 18px; + font-weight: 600; + color: #fff; + line-height: 1.8em; } + #contact > .mapInfo > .inner > ul > li > span { + color: #111; + font-weight: 900; } + +@media screen and (max-width: 768px) { + /*contact 768px 반응형*/ + #contact { + width: 100%; + height: auto; + background-color: #263d78; } + #contact > h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #fff; + text-transform: uppercase; } + #contact > h3:after { + position: absolute; + bottom: -20px; + left: 50.2%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #111; + letter-spacing: 4px; + content: "How to come"; } + #contact > .mapContainer { + width: 90%; + height: 450px; + margin: 60px auto 40px; } + #contact > .mapContainer > .map { + width: 100%; + height: 450px; + background-image: url(../images/map_eng_18.08.06.jpg); + background-position: 10% 50%; + background-size: cover; + border: 0; } + #contact > .mapContainer > .map > a { + display: block; + width: 100%; + height: 100%; + text-indent: -99999px; } + #contact > .mapInfo { + position: relative; + width: 100%; + text-align: center; + padding-bottom: 50px; } + #contact > .mapInfo:after { + display: none; + position: absolute; + top: 0; + left: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: 0 50%; + content: ''; } + #contact > .mapInfo:before { + display: none; + position: absolute; + bottom: 0; + right: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: -35px 50%; + content: ''; } + #contact > .mapInfo > .inner > ul > li { + font-size: 18px; + font-weight: 600; + color: #fff; + line-height: 1.8em; } + #contact > .mapInfo > .inner > ul > li > span { + display: block; + color: #111; + font-weight: 900; } } +@media screen and (max-width: 768px) { + #status > .status > ul > li.status_info_main:after { + display: none; } } +#since_eng { + width: 100%; + margin-bottom: 60px; + height: 850px; + background-color: #fff; } + #since_eng > .since { + position: relative; + width: 1000px; + margin: 0 auto; } + #since_eng > .since > ul { + margin-top: 80px; + width: 100%; } + #since_eng > .since > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #since_eng > .since > ul > li.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: #263d78; + margin-bottom: 55px; + line-height: 1.3em; + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ } + #since_eng > .since > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #since_eng > .since > ul > li > em { + color: #ffc700; } + #since_eng > .since > ul > li > span { + font-size: 20px; } + #since_eng > .since > .since_info { + width: 100%; } + #since_eng > .since > .since_info > h2 { + font-size: 50px; + font-weight: 500; + font-style: italic; + letter-spacing: -4px; + color: #eee; } + #since_eng > .since > .since_info > div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; } + #since_eng > .since > .since_info > div > ul { + width: 100%; } + #since_eng > .since > .since_info > div > ul > li { + float: left; + margin-left: 230px; + line-height: 2.2em; } + #since_eng > .since > .since_info > div > ul > li:first-child { + font-size: 40px; + font-weight: 900; + color: #ddd; } + #since_eng > .since > .since_info > div > ul > li > dl { + padding: 5px 10px; + width: 100%; } + #since_eng > .since > .since_info > div > ul > li > dl > dd { + position: relative; + font-size: 15px; + font-weight: 600; } + #since_eng > .since > .since_info > div > ul > li > dl > dd:after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: -20px; + width: 10px; + height: 10px; + border-radius: 15px; + background-color: #ffc700; + content: ''; } + +@media screen and (max-width: 768px) { + #since_eng { + width: 100%; + margin-bottom: 0px; + padding-bottom: 80px; + height: auto; + background-color: #fff; } + #since_eng > .since { + position: relative; + width: 90%; + margin: 0 auto; } + #since_eng > .since > ul { + margin-top: 80px; + width: 100%; } + #since_eng > .since > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #since_eng > .since > ul > li.status_info_main { + position: relative; + font-size: 22px; + font-weight: 600; + color: #263d78; + margin-bottom: 55px; + line-height: 1.3em; + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ } + #since_eng > .since > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #since_eng > .since > ul > li > em { + color: #ffc700; } + #since_eng > .since > ul > li > span { + font-size: 20px; } + #since_eng > .since > .since_info { + width: 100%; } + #since_eng > .since > .since_info > h2 { + padding-bottom: 20px; + padding-left: 0px; + font-size: 50px; + font-weight: 500; + font-style: italic; + letter-spacing: -4px; + color: #eee; } + #since_eng > .since > .since_info > div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; } + #since_eng > .since > .since_info > div > ul { + padding-left: 0px; + width: 100%; } + #since_eng > .since > .since_info > div > ul > li { + float: inherit; + margin-left: 0px; + line-height: 1.45em; } + #since_eng > .since > .since_info > div > ul > li:first-child { + display: none; + font-size: 40px; + font-weight: 900; + color: #ddd; } + #since_eng > .since > .since_info > div > ul > li > dl { + padding: 5px 0px; + width: 100%; } + #since_eng > .since > .since_info > div > ul > li > dl > dd { + position: relative; + font-size: 14px; + font-weight: 500; + padding-bottom: 10px; } + #since_eng > .since > .since_info > div > ul > li > dl > dd:after { + position: absolute; + top: 11px; + transform: translateY(-50%); + left: -10px; + width: 5px; + height: 5px; + border-radius: 15px; + background-color: #ffc700; + content: ''; } } +/*certificate*/ +#certificate_eng { + width: 100%; + padding-bottom: 20px; + margin-bottom: 0px; + height: auto; + background-color: #fff; } + #certificate_eng > .certificate_eng { + position: relative; + width: 1000px; + margin: 0 auto; } + #certificate_eng > .certificate_eng > ul { + margin-top: 80px; + width: 100%; } + #certificate_eng > .certificate_eng > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #certificate_eng > .certificate_eng > ul > li.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: #263d78; + margin-bottom: 55px; + line-height: 1.3em; } + #certificate_eng > .certificate_eng > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #certificate_eng > .certificate_eng > ul > li > em { + color: #ddd; } + #certificate_eng > .certificate_eng > ul > li > span { + font-size: 20px; } + #certificate_eng > .certificate_eng > .certificate_info_eng { + width: 100%; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div { + width: 100%; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div > ul > li { + float: left; + margin: 0 47px 50px 0; + width: 300px; + height: 400px; + border: 1px dotted #eee; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div > ul > li:last-child { + margin-right: 0; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div > ul > li > dl > dt { + width: 100%; + height: 350px; + text-indent: -99999px; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div > ul > li > dl > dd { + padding-top: 5px; + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 20px; } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect01_eng > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect01_eng > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect01_eng > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect02_eng > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect02_eng > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect02_eng > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect03_eng > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect03_eng > ul > li:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect03_eng > ul > li:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_10.png); + background-position: 50% 50%; } + +@media screen and (max-width: 768px) { + #certificate_eng { + width: 100%; + margin-bottom: 0 auto 0; + height: auto; + background-color: #fff; } + #certificate_eng > .index_tap > p > span > a { + padding-right: 240px; } + #certificate_eng > .certificate_eng { + position: relative; + width: 100%; + margin: 0 auto; } + #certificate_eng > .certificate_eng > ul { + margin-top: 80px; + width: 100%; } + #certificate_eng > .certificate_eng > ul > li { + width: 100%; + text-align: center; + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #certificate_eng > .certificate_eng > ul > li.status_info_main { + position: relative; + font-size: 22px; + font-weight: 700; + color: #263d78; + margin-bottom: 55px; + line-height: 1.3em; } + #certificate_eng > .certificate_eng > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #certificate_eng > .certificate_eng > ul > li > em { + color: #ddd; } + #certificate_eng > .certificate_eng > ul > li > span { + font-size: 20px; } + #certificate_eng > .certificate_eng > .certificate_info_eng { + width: 100%; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div { + width: 100%; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div > ul { + width: 100%; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div > ul > li { + float: inherit; + margin: 0 0px 50px 0; + width: 100%; + height: 400px; + border: 1px dotted #eee; + border-top: none; + border-left: none; + border-right: none; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div > ul > li:last-child { + margin-right: 0; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div > ul > li > dl > dt { + width: 100%; + height: 350px; + text-indent: -99999px; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; } + #certificate_eng > .certificate_eng > .certificate_info_eng > div > ul > li > dl > dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect01_eng > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect01_eng > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect01_eng > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect02_eng > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect02_eng > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect02_eng > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect03_eng > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect03_eng > ul > li:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; } + #certificate_eng > .certificate_eng > .certificate_info_eng > .sect03_eng > ul > li:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_10.png); + background-position: 50% 50%; } } +#research { + width: 100%; + background-color: white; } + #research > .inner { + width: 100%; + height: 180px; + padding-top: 60px; + margin: 0 auto; + background-image: url(../images/research_m01.jpg); } + #research > .inner > h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + color: #fff; } + #research > .inner > h2:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #research > .inner > .threeTap { + width: 100%; } + #research > .inner > .threeTap ul { + width: 1370px; + margin: 0 auto; } + #research > .inner > .threeTap ul > li { + display: block; + float: left; + margin: 0 10px; + font-size: 20px; + font-weight: 600; + color: #fff; + cursor: default; } + #research > .research { + padding-top: 130px; + margin-bottom: 100px; + width: 100%; } + #research > .research > div { + width: 100%; } + #research > .research > div > ul > li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #research > .research > div > ul > li:first-child { + text-indent: -99999px; } + #research > .research > div > ul > li:last-child { + height: 240px; + margin-top: 120px; } + #research > .research > div > ul > li:last-child > dl { + padding-left: 100px; } + #research > .research > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #research > .research > div > ul > li:last-child > dl > dt:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #research > .research > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #263d78; + font-weight: 500; } + #research > .research > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #research > .research > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #263d78; + border-radius: 7px; + content: ''; } + #research > .research > div.research_01 > ul > li:first-child { + background-image: url(../images/camera.png); + background-size: contain; } + #research > .research > div.research_02 { + width: 100%; + height: 100%; + background-image: url(../images/bg_2.png); } + #research > .research > div.research_02 > ul > li > dl dt { + color: #fff; } + #research > .research > div.research_02 > ul > li > dl dd { + color: #fff; } + #research > .research > div.research_02 > ul > li:first-child { + background-image: url(../images/crack.png); + background-size: contain; } + #research > .research > div.research_03 > ul > li:first-child { + background-image: url(../images/moon.png); + background-size: contain; + background-repeat: no-repeat; } + +@media screen and (max-width: 768px) { + #research { + width: 100%; + background-color: white; } + #research > .inner { + height: 250px; + padding-top: 30px; + margin: 0 auto; + background-image: url(../images/research_m01.jpg); } + #research > .inner > h2 { + position: relative; + text-align: center; + font-size: 22px; + font-weight: 600; + margin-bottom: 50px; } + #research > .inner > h2:after { + position: absolute; + top: 50px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #research > .inner > .threeTap { + width: 100%; + height: 100%; } + #research > .inner > .threeTap ul { + width: 100%; + margin: 0 auto; } + #research > .inner > .threeTap ul > li { + display: block; + float: inherit; + text-align: center; + margin: 10px 20px; + font-size: 20px; + font-weight: 600; + color: #fff; + cursor: default; } + #research > .category { + position: fixed; + bottom: 0; + width: 100%; + border-bottom: 1px solid #ddd; + z-index: 99999; } + #research > .category > ul { + margin: 0 auto; + width: 100%; } + #research > .category > ul > li { + float: left; + width: 25%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px; + background-color: #eee; + color: #555; + cursor: pointer; } + #research > .category > ul > li:last-child { + margin-right: 0; + border-bottom: none; } + #research > .category > ul > li:hover { + color: #fff; + background-color: #263d78; } + #research > .category > ul > li.on { + color: #fff; + background-color: #263d78; } + #research > .research { + padding-top: 0px; + width: 100%; + background-image: url(../images/bus_bg.jpg); } + #research > .research > div { + width: 100%; + margin-top: 30px; } + #research > .research > div:first-child { + margin-top: 0; } + #research > .research > div > ul > li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #research > .research > div > ul > li:first-child { + height: 200px; + float: inherit !important; + text-indent: -99999px; } + #research > .research > div > ul > li:last-child { + height: auto; + margin-top: 20px; } + #research > .research > div > ul > li:last-child > dl { + width: 90%; + padding-left: 0px; + margin: 0 auto; } + #research > .research > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #research > .research > div > ul > li:last-child > dl > dt:after { + display: none; + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #research > .research > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #263d78; + font-weight: 500; } + #research > .research > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #research > .research > div > ul > li:last-child > dl > dd > br { + display: none; } + #research > .research > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #263d78; + border-radius: 7px; + content: ''; } + #research > .research > div.research_01 > ul > li:first-child { + background-image: url(../images/camera.png); + background-size: contain; } + #research > .research > div.research_02 { + width: 100%; + height: 100%; + background-image: url(../images/bg_2.png); } + #research > .research > div.research_02 > ul > li > dl dt { + color: #fff; } + #research > .research > div.research_02 > ul > li > dl dd { + color: #fff; } + #research > .research > div.research_02 > ul > li:first-child { + background-image: url(../images/crack.png); + background-size: contain; } + #research > .research > div.research_03 > ul > li:first-child { + background-image: url(../images/moon.png); + background-size: contain; + background-repeat: no-repeat; } } +/*business*/ +#business_eng { + width: 100%; + background-color: white; } + #business_eng > .inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; } + #business_eng > .inner > h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; } + #business_eng > .inner > h2:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #business_eng > .inner p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; } + #business_eng > .category { + width: 100%; + border-bottom: 1px solid #eee; } + #business_eng > .category > ul { + margin: 0 auto; + width: 850px; } + #business_eng > .category > ul > li { + float: left; + width: 24%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 3px; + background-color: #ddd; + color: #555; + cursor: pointer; } + #business_eng > .category > ul > li:last-child { + margin-right: 0; } + #business_eng > .category > ul > li:hover { + color: #fff; + background-color: #263d78; } + #business_eng > .category > ul > li.on { + color: #fff; + background-color: #263d78; } + #business_eng > .business { + padding-top: 130px; + width: 100%; + background-image: url(../images/bus_bg.jpg); } + #business_eng > .business > div { + width: 100%; } + #business_eng > .business > div > ul > li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #business_eng > .business > div > ul > li:first-child { + text-indent: -99999px; } + #business_eng > .business > div > ul > li:last-child { + height: 240px; + margin-top: 120px; } + #business_eng > .business > div > ul > li:last-child > dl { + padding-left: 50px; } + #business_eng > .business > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 40px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #business_eng > .business > div > ul > li:last-child > dl > dt:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #business_eng > .business > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #263d78; + font-weight: 500; } + #business_eng > .business > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #business_eng > .business > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #263d78; + border-radius: 7px; + content: ''; } + #business_eng > .business > div.business_01 > ul > li:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; } + #business_eng > .business > div.business_02 > ul > li:first-child { + background-image: url(../images/bigdata.jpg); + background-size: contain; } + #business_eng > .business > div.business_02 > ul > li > dl > dd:nth-child(3):after { + top: 50%; } + #business_eng > .business > div.business_02 > ul > li > dl > dd:nth-child(4):after { + top: 50%; } + #business_eng > .business > div.business_03 > ul > li:first-child { + background-image: url(../images/soc.jpg); + background-size: contain; + background-repeat: no-repeat; } + #business_eng > .business > div.business_04 { + padding-bottom: 100px; } + #business_eng > .business > div.business_04 > ul > li:first-child { + background-image: url(../images/si.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 0 88%; } + +@media screen and (max-width: 768px) { + #business_eng { + width: 100%; + background-color: white; } + #business_eng > .inner { + height: 50px; + padding-top: 60px; + margin: 0 auto 130px; } + #business_eng > .inner > h2 { + position: relative; + text-align: center; + font-size: 22px; + line-height: 1.3em; + font-weight: 600; + margin-bottom: 50px; } + #business_eng > .inner > h2 > span { + display: block; } + #business_eng > .inner > h2:after { + position: absolute; + top: 80px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #business_eng > .inner p { + width: 90%; + margin: 0 auto; + text-align: center; + font-size: 15px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; } + #business_eng > .inner p > br { + display: none; } + #business_eng > .category { + position: fixed; + bottom: 0; + width: 100%; + border-bottom: 1px solid #ddd; + z-index: 99999; } + #business_eng > .category > ul { + margin: 0 auto; + width: 100%; } + #business_eng > .category > ul > li { + float: left; + width: 25%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px; + background-color: #eee; + color: #555; + cursor: pointer; } + #business_eng > .category > ul > li:last-child { + margin-right: 0; + border-bottom: none; } + #business_eng > .category > ul > li:hover { + color: #fff; + background-color: #263d78; } + #business_eng > .category > ul > li.on { + color: #fff; + background-color: #263d78; } + #business_eng > .business { + padding-top: 0px; + width: 100%; + background-image: url(../images/bus_bg.jpg); } + #business_eng > .business > div { + width: 100%; + margin-top: 30px; } + #business_eng > .business > div:first-child { + margin-top: 0; } + #business_eng > .business > div > ul > li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #business_eng > .business > div > ul > li:first-child { + height: 200px; + float: inherit !important; + text-indent: -99999px; } + #business_eng > .business > div > ul > li:last-child { + height: auto; + margin-top: 20px; } + #business_eng > .business > div > ul > li:last-child > dl { + width: 90%; + padding-left: 0px; + margin: 0 auto; } + #business_eng > .business > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #business_eng > .business > div > ul > li:last-child > dl > dt:after { + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #business_eng > .business > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #263d78; + font-weight: 500; } + #business_eng > .business > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #business_eng > .business > div > ul > li:last-child > dl > dd > br { + display: none; } + #business_eng > .business > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #263d78; + border-radius: 7px; + content: ''; } + #business_eng > .business > div.business_01 > ul > li:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; } + #business_eng > .business > div.business_02 > ul > li:first-child { + background-image: url(../images/bigdata.jpg); + background-size: contain; } + #business_eng > .business > div.business_03 > ul > li:first-child { + background-image: url(../images/soc.jpg); + background-size: cover; + background-repeat: no-repeat; } + #business_eng > .business > div.business_03 > ul > li:last-child > dl > dt:after { + position: absolute; + top: 80px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #business_eng > .business > div.business_04 { + padding-bottom: 40px; } + #business_eng > .business > div.business_04 > ul > li:first-child { + background-image: url(../images/si.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 90%; } + #business_eng > .business > div.business_04 > ul > li:last-child > dl > dt:after { + position: absolute; + top: 80px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } } +/*contact*/ +#faq_eng { + position: relative; + width: 100%; + margin-bottom: 60px; + height: 600px; + background-color: #fff; } + #faq_eng > .inner { + width: 1000px; + margin: 0 auto; } + #faq_eng > .inner > .faq_info { + float: left; + width: 450px; + margin: 0 auto; } + #faq_eng > .inner > .faq_info > ul { + margin-top: 80px; + width: 100%; } + #faq_eng > .inner > .faq_info > ul > li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; } + #faq_eng > .inner > .faq_info > ul > li:last-child { + margin-top: 50px; + font-size: 17px; + font-weight: 600; } + #faq_eng > .inner > .faq_info > ul > li > span { + font-size: 20px; + font-weight: 600; } + #faq_eng > .inner > .faq_info > ul > li > em { + color: #eee; } + #faq_eng > .inner > .faq_info > ul > li.faq_info_main { + position: relative; + font-size: 29px; + font-weight: 700; + color: #263d78; + margin-bottom: 55px; + line-height: 1.3em; } + #faq_eng > .inner > .faq_info > ul > li.faq_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #faq_eng > .inner > .map { + float: right; + margin-top: 50px; + width: 540px; + height: 400px; + border: 0; } + +@media screen and (max-width: 768px) { + #faq_eng { + position: relative; + width: 100%; + padding-bottom: 60px; + margin-bottom: 0px; + height: auto; + background-color: #fff; } + #faq_eng > .inner { + width: 100%; + margin: 0 auto; } + #faq_eng > .inner > .faq_info { + float: inherit; + width: 90%; + margin: 0 auto; } + #faq_eng > .inner > .faq_info > ul { + margin-top: 80px; + width: 100%; } + #faq_eng > .inner > .faq_info > ul > li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; } + #faq_eng > .inner > .faq_info > ul > li:last-child { + border-top: 1px dotted #ddd; + margin-top: 20px; + padding-top: 10px; + font-size: 14px; + color: #263d78; + font-weight: 600; } + #faq_eng > .inner > .faq_info > ul > li > span { + font-size: 17px; + font-weight: 600; } + #faq_eng > .inner > .faq_info > ul > li > em { + color: #eee; } + #faq_eng > .inner > .faq_info > ul > li.faq_info_main { + position: relative; + text-align: center; + font-size: 22px; + font-weight: 700; + color: #263d78; + margin-bottom: 55px; + line-height: 1.3em; } + #faq_eng > .inner > .faq_info > ul > li.faq_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #faq_eng > .inner > .map { + float: inherit; + width: 100%; + height: 450px; + background-image: url(../images/map_eng_18.08.06.jpg); + background-position: 10% 50%; + background-size: cover; + border: 0; } } +footer { + width: 100%; + height: 170px; + background-color: #333; } + footer > .inner { + position: relative; + padding-top: 20px; } + footer > .inner > h1 { + float: left; + margin-left: 40px; + width: 120px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; } + footer > .inner > address { + float: left; + margin-top: 0px; + margin-left: 30px; + width: 350px; } + footer > .inner > address > ul { + width: 350px; } + footer > .inner > address > ul > li { + margin-left: 0px; + width: 320px; + text-align: center; } + footer > .inner > address > ul > li:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); } + footer > .inner > address > ul > li:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); } + footer > .inner > address > ul > li:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); } + footer > .inner > address > ul > li > dl > dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + footer > .inner > address > ul > li > dl > dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > address > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > address > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a:hover { + text-decoration: underline; } + footer > .inner > .f_nav { + float: right; + margin-top: 0px; + width: 200px; } + footer > .inner > .f_nav > ul > li { + float: left; + margin-right: 9px; + padding-right: 11px; + background-image: url(../images/f_right.png); + background-repeat: no-repeat; + background-position: 100% 73%; } + footer > .inner > .f_nav > ul > li:last-child { + margin-right: none; + background-image: none; } + footer > .inner > .f_nav > ul > li > a { + font-size: 13px; + color: #fff; } + footer > .inner > .copyright { + position: absolute; + top: 120px; + right: -140px; + transform: translateX(-50%); + width: 315px; + font-size: 13px; + letter-spacing: 1px; + color: #fff; } + footer > .inner:after { + position: absolute; + top: 30px; + left: 180px; + transform: translateX(-50%); + width: 1px; + height: 120px; + background-color: #fff; + content: ''; } + +@media screen and (max-width: 768px) { + /*footer 768px 반응형*/ + footer { + width: 100%; + height: auto; + background-color: #333; } + footer > .inner { + position: relative; + padding-top: 20px; } + footer > .inner > h1 { + float: inherit; + margin: 0 auto 180px; + width: 120px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; } + footer > .inner > .f_left { + float: inherit; + margin: 0 auto; + width: 100%; } + footer > .inner > .f_left > ul { + width: 100%; } + footer > .inner > .f_left > ul > li { + width: 100%; } + footer > .inner > .f_left > ul > li > dl > dt { + display: none; + margin: 0 auto; + width: 100%; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + footer > .inner > .f_left > ul > li > dl > dd { + padding-left: 20px; + text-align: left; + margin-top: 8px; + font-size: 16px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > .f_left > ul > li > dl > dd > em { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > .f_left > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > .f_left > ul > li > dl > dd > a:hover { + text-decoration: none; } + footer > .inner > address { + border-top: 1px solid #666; + float: inherit; + margin: 10px 0; + width: 100%; } + footer > .inner > address > ul { + width: 100%; } + footer > .inner > address > ul > li { + width: 100%; + text-align: center; } + footer > .inner > address > ul > li:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); } + footer > .inner > address > ul > li:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); } + footer > .inner > address > ul > li:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); } + footer > .inner > address > ul > li > dl > dt { + display: none; } + footer > .inner > address > ul > li > dl > dd { + padding-left: 25px; + text-align: left; + margin-top: 6px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; } + footer > .inner > address > ul > li > dl > dd:nth-child(2) { + font-weight: 700; } + footer > .inner > address > ul > li > dl > dd:nth-child(3) { + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a { + font-size: 13px; + color: #909090; } + footer > .inner > address > ul > li > dl > dd > a > span { + display: block; } + footer > .inner > address > ul > li > dl > dd > a > span > span { + display: block; } + footer > .inner > address > ul > li > dl > dd > a:hover { + text-decoration: underline; } + footer > .inner > .f_nav { + position: absolute; + top: 75px; + float: inherit; + margin-top: 0px; + width: 100%; } + footer > .inner > .f_nav > ul > li { + width: 100%; + text-align: center; + float: inherit; + margin-right: 0px; + padding-right: 0px; + background-image: none; + background-repeat: no-repeat; + background-position: 100% 73%; + border-top: 1px solid #666; } + footer > .inner > .f_nav > ul > li:last-child { + margin-right: none; + background-image: none; + border-bottom: 1px solid #666; } + footer > .inner > .f_nav > ul > li > a { + display: block; + height: 50px; + line-height: 50px; + font-size: 16px; + color: #fff; } + footer > .inner > .copyright { + border-top: 1px solid #666; + position: static; + padding: 20px 0; + top: 10px; + right: 50%; + transform: translateX(0); + width: 100%; + font-size: 13px; + letter-spacing: 1px; + text-align: center; + color: #fff; } + footer > .inner:after { + display: none; } } + +/*# sourceMappingURL=common_eng.css.map */ diff --git a/eng/css/common_eng.css.map b/eng/css/common_eng.css.map new file mode 100644 index 0000000..a6101d4 --- /dev/null +++ b/eng/css/common_eng.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["common_eng.scss"], +"names": [], +"file": "common_eng.css" +} \ No newline at end of file diff --git a/eng/css/common_eng.scss b/eng/css/common_eng.scss new file mode 100644 index 0000000..38149e4 --- /dev/null +++ b/eng/css/common_eng.scss @@ -0,0 +1,2432 @@ +$point-color : #263d78; +$point-color2 : #ffc700; + +#contact { + width: 100%; + height: 750px; + background-color: $point-color; + + >h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #fff; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -20px; + left: 50.2%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #111; + letter-spacing: 4px; + content: "How to come"; + }//end of :after + }//end of h3 + + >.mapContainer { + width: 600px; + height: 300px; + margin: 60px auto 200px; + + >.map { + width : 600px; + height : 450px; + + background-image: url(../images/map_eng_18.08.06.jpg); + background-position: 50% 50%; + background-size: cover; + border : 0; + + >a { + display: block; + width: 100%; + height: 100%; + text-indent: -99999px; + } + }//end of map + }//end of mapContainer + + >.mapInfo { + position: relative; + width: 100%; + text-align: center; + + &:after { + position: absolute; + top: 0; + left: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: 0 50%; + content: ''; + }//end of :after + + &:before { + position: absolute; + bottom: 0; + right: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: -35px 50%; + content: ''; + }//end of :after + + + >.inner { + >ul { + >li { + font-size: 18px; + font-weight: 600; + color: #fff; + line-height: 1.8em; + + >span { + color: #111; + font-weight: 900; + }//end of span + }//end of li + }//end of ul + }//end of inner + }//end of mapInfo + +}//end of #contact + + + + +@media screen and(max-width : 768px) {/*contact 768px 반응형*/ + + #contact { + width: 100%;//변경 + height: auto;//변경 + background-color: $point-color; + + >h3 { + position: relative; + padding: 50px 0 0; + font-weight: 600; + text-align: center; + color: #fff; + text-transform: uppercase; + + &:after { + position: absolute; + bottom: -20px; + left: 50.2%; + transform: translateX(-50%); + font-size: 15px; + font-weight: 800; + color: #111; + letter-spacing: 4px; + content: "How to come"; + }//end of :after + }//end of h3 + + >.mapContainer { + width: 90%;//변경 + height: 450px; + margin: 60px auto 40px; + + >.map { + width : 100%; + height : 450px; + + background-image: url(../images/map_eng_18.08.06.jpg); + background-position: 10% 50%; + background-size: cover; + border : 0; + + >a { + display: block; + width: 100%; + height: 100%; + text-indent: -99999px; + } + }//end of map + }//end of mapContainer + + >.mapInfo { + position: relative; + width: 100%; + text-align: center; + padding-bottom: 50px;//추가 + + &:after { + display: none;//추가 + position: absolute; + top: 0; + left: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: 0 50%; + content: ''; + }//end of :after + + &:before { + display: none;//추가 + position: absolute; + bottom: 0; + right: 20%; + width: 35px; + height: 30px; + background-image: url(../images/bg_quote.png); + background-position: -35px 50%; + content: ''; + }//end of :after + + + >.inner { + >ul { + >li { + font-size: 18px; + font-weight: 600; + color: #fff; + line-height: 1.8em; + + >span { + display: block; + color: #111; + font-weight: 900; + }//end of span + }//end of li + }//end of ul + }//end of inner + }//end of mapInfo + + }//end of #contact + +}//contact 768px 반응형 + + +@media screen and(max-width : 768px) { + #status > .status > ul > li.status_info_main:after { + display: none; + } +} + +#since_eng { + width: 100%; + margin-bottom: 60px; + //background-color: green; + + + height: 850px; + background-color: #fff; + + + >.since { + position: relative; + width: 1000px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ + }//end of ceo_info_main + + >em { + color: $point-color2; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + + >.since_info { + width: 100%; + //background-color: orange; + + >h2 { + //padding-left: 100px; + font-size: 50px; + font-weight: 500; + font-style : italic; + letter-spacing: -4px; + color: #eee; + + } + + >div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; + + >ul { + //padding-left: 150px; + width: 100%; + + >li { + float: left; + margin-left: 230px; + line-height: 2.2em; + + &:first-child { + font-size: 40px; + font-weight: 900; + color: #ddd; + }//end of all li:first-child + + >dl { + padding: 5px 10px; + width: 100%; + //background-color: red; + + + >dd { + position: relative; + font-size: 15px; + font-weight: 600; + + &:after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: -20px; + width: 10px; + height: 10px; + border-radius: 15px; + background-color: $point-color2; + content: ''; + } + }//end of all dd + }//end of all dl + + }//end of all li + }//end of all ul + }//end of all div + + >.january { + + >ul { + //background-color: pink; + }//end of ul + }//end of january + + >.february { + + >ul { + //background-color: green; + }//end of ul + }//end of february + + >.march { + + >ul { + //background-color: rgb(0, 186, 191); + }//end of ul + }//end of march + }//end of since_info + + }//end of ceo_info + +}//end of since + +@media screen and(max-width : 768px) {//since eng 768px --반응형때 + + #since_eng { + width: 100%; + margin-bottom: 0px;//변경 + padding-bottom: 80px;//추가 + //background-color: green; + + + height: auto;//변경 + background-color: #fff; + + + >.since { + position: relative; + width: 90%; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 22px;//변경 + font-weight: 600;//변경 + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ + }//end of ceo_info_main + + >em { + color: $point-color2; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + + >.since_info { + width: 100%; + //background-color: orange; + + >h2 { + padding-bottom: 20px;//추가 + padding-left: 0px;//변경 + font-size: 50px; + font-weight: 500; + font-style : italic; + letter-spacing: -4px; + color: #eee; + + } + + >div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; + + >ul { + padding-left: 0px;//변경 + width: 100%; + + >li { + float: inherit; + margin-left: 0px;//변경 + line-height: 1.45em; + + &:first-child { + display: none; + font-size: 40px; + font-weight: 900; + color: #ddd; + }//end of all li:first-child + + >dl { + padding: 5px 0px;//변경 + width: 100%; + //background-color: red; + + + >dd { + position: relative; + font-size: 14px; + font-weight: 500; + padding-bottom: 10px;//추가 + + &:after { + position: absolute; + top: 11px; + transform: translateY(-50%); + left: -10px; + width: 5px; + height: 5px; + border-radius: 15px; + background-color: $point-color2; + content: ''; + } + }//end of all dd + }//end of all dl + + }//end of all li + }//end of all ul + }//end of all div + + >.january { + + >ul { + //background-color: pink; + }//end of ul + }//end of january + + >.february { + + >ul { + //background-color: green; + }//end of ul + }//end of february + + >.march { + + >ul { + //background-color: rgb(0, 186, 191); + }//end of ul + }//end of march + }//end of since_info + + }//end of ceo_info + + }//end of since + +}//since eng 768px 반응형 + + + +/*certificate*/ + +#certificate_eng { + width: 100%; + padding-bottom: 20px; + margin-bottom: 0px; + //background-color: green; + + + height: auto; + background-color: #fff; + + + >.certificate_eng { + position: relative; + width: 1000px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #ddd; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >.certificate_info_eng { + width: 100%; + //background-color: green; + + >div { + width: 100%; + + >ul { + + >li { + float: left; + margin: 0 47px 50px 0; + width: 300px; + height: 400px; + //background-color: pink; + border: 1px dotted #eee; + + &:last-child { + margin-right: 0; + } + + >dl { + + >dt { + width: 100%; + height: 350px; + text-indent: -99999px; + //background-color: orange; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + } + >dd { + padding-top: 5px; + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 20px; + } + }//end of all dl + }//end of all li + }//end of all ul + }//end of all div + + + >.sect01_eng >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); + } + + }//end of sect01 img + + >.sect02_eng >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); + } + + }//end of sect02 img + + + >.sect03_eng >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); + } + &:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; + } + &:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_10.png); + background-position: 50% 50%; + } + + + }//end of sect03 img + + }//end of certificate_info--> + + }//end of ceo_info + +}//end of certificate + + +@media screen and(max-width : 768px) {//certificate 768px 반응형 + + + #certificate_eng { + width: 100%;//변경 + margin-bottom: 0 auto 0;//변경 + //background-color: green; + height: auto;//변경 + background-color: #fff; + + >.index_tap { + >p { + >span { + + >a { + padding-right: 240px; + } + } + } + } + + + >.certificate_eng { + position: relative; + width: 100%; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + width: 100%;//추가 + text-align: center; + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 22px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #ddd; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >.certificate_info_eng { + width: 100%; + //background-color: green; + + >div { + width: 100%; + + >ul { + width: 100%;//추가 + + >li { + float: inherit; + margin: 0 0px 50px 0; + width: 100%; + height: 400px; + //background-color: pink; + border: 1px dotted #eee; + border-top: none;//추가 + border-left: none;//추가 + border-right: none;//추가 + + &:last-child { + margin-right: 0; + } + + >dl { + + >dt { + width: 100%; + height: 350px; + text-indent: -99999px; + //background-color: orange; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; + } + >dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; + } + }//end of all dl + }//end of all li + }//end of all ul + }//end of all div + + + >.sect01_eng >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); + } + + }//end of sect01 img + + >.sect02_eng >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); + } + + }//end of sect02 img + + + >.sect03_eng >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); + } + &:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; + } + &:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_10.png); + background-position: 50% 50%; + } + + + }//end of sect03 img + + }//end of certificate_info--> + + }//end of ceo_info + + }//end of certificate + + + +}//certificate 768px 반응형 + + +#research { + width: 100%; + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + width: 100%; + height: 180px; + padding-top: 60px; + margin: 0 auto; + background-image: url(../images/research_m01.jpg); + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + color: #fff; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + + >.threeTap { + width: 100%; + //height: 40px; + //background-color: green; + ul { + width: 1370px; + margin: 0 auto; + //background-color: pink; + >li { + display: block; + float: left; + margin: 0 10px; + font-size: 20px; + font-weight: 600; + color: #fff; + cursor: default; + + } + } + }//end of threetap + }//end of inner + + + >.research { + padding-top: 130px; + margin-bottom : 100px; + width: 100%; + //background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + //margin-top: 60px; + + >ul { + //background-color: green; + >li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + text-indent: -99999px; + + + } + + &:last-child { + + height: 240px; + margin-top: 120px; + //background-color: red; + + + >dl{ + padding-left: 100px; + >dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.research_01 { + >ul >li { + + &:first-child { + background-image: url(../images/camera.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of research_01 + + &.research_02 { + width: 100%; + height: 100%; + background-image: url(../images/bg_2.png); + >ul >li { + >dl{ + dt{ + color: #fff; + } + dd { + color: #fff; + } + } + + &:first-child { + background-image: url(../images/crack.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of research_02 + + &.research_03 { + >ul >li { + + &:first-child { + background-image: url(../images/moon.png); + background-size: contain; + background-repeat: no-repeat; + //background-color: orange; + } + }//end of 01 li + }//end of research_03 + + }//end of all div + + }//end of class business +}//end of #research + + + + + + +@media screen and(max-width : 768px) {//research 768px 반응형 + + #research { + width: 100%; + + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + height: 250px; + padding-top: 30px; + margin: 0 auto; + background-image: url(../images/research_m01.jpg); + + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 22px;//변경 + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 50px;//변경 + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + >.threeTap { + width: 100%; + height: 100%; + //background-color: green; + ul { + width: 100%; + margin: 0 auto; + //background-color: pink; + >li { + display: block; + float: inherit;//변경 + text-align: center;//추가 + margin: 10px 20px;//변경 + font-size: 20px; + font-weight: 600; + color: #fff; + cursor: default; + + } + } + }//end of threetap + }//end of inner + + >.category { + position: fixed;//추가 + bottom: 0;//추가 + width: 100%; + border-bottom: 1px solid #ddd;//변경 + z-index: 99999; + //ackground-color: green; + + >ul { + margin: 0 auto; + width: 100%;//변경 + + + >li { + float: left;//변경 + width: 25%;//변경 + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px;//변경 + background-color: #eee; + //border-bottom: 1px solid #555; + + color: #555; + cursor: pointer; + + &:last-child { + margin-right: 0; + border-bottom: none; + } + + &:hover { + color:#fff; + background-color: $point-color; + } + + &.on { + color:#fff; + background-color: $point-color; + } + + + }//end of li + }//end of ul + }//end of category + + >.research { + padding-top: 0px;//변경 + width: 100%; + background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + margin-top: 30px;//추가 + + &:first-child { + margin-top: 0; + } + + + >ul { + //background-color: green; + >li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + height: 200px; + float: inherit!important;//추가 + text-indent: -99999px; + + + } + + &:last-child { + height: auto; + margin-top: 20px;//변경 + //background-color: red; + + + >dl{ + width: 90%;//추기 + padding-left: 0px; + margin: 0 auto;//추가 + >dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + display: none; + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + >br { + display: none; + } + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.research_01 { + >ul >li { + + &:first-child { + background-image: url(../images/camera.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of research_01 + + &.research_02 { + width: 100%; + height: 100%; + background-image: url(../images/bg_2.png); + >ul >li { + >dl{ + dt{ + color: #fff; + } + dd { + color: #fff; + } + } + + &:first-child { + background-image: url(../images/crack.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of research_02 + + &.research_03 { + >ul >li { + + &:first-child { + background-image: url(../images/moon.png); + background-size: contain; + background-repeat: no-repeat; + //background-color: orange; + } + }//end of 01 li + }//end of research_03 + + }//end of all div + + }//end of class business + }//end of #business + +}//research 768px 반응형 + + +/*business*/ + +#business_eng { + width: 100%; + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + >.category { + width: 100%; + border-bottom: 1px solid #eee; + //ackground-color: green; + + >ul { + margin: 0 auto; + width: 850px; + + + >li { + float: left; + width: 24%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 3px; + background-color: #ddd; + color: #555; + cursor: pointer; + + &:last-child { + margin-right: 0; + } + + &:hover { + color:#fff; + background-color: $point-color; + } + + &.on { + color:#fff; + background-color: $point-color; + } + + + }//end of li + }//end of ul + }//end of category + + >.business { + padding-top: 130px; + width: 100%; + background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + //margin-top: 60px; + + >ul { + //background-color: green; + >li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + text-indent: -99999px; + + + } + + &:last-child { + + height: 240px; + margin-top: 120px; + //background-color: red; + + + >dl{ + padding-left: 50px; + >dt { + position: relative; + font-size: 40px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.business_01 { + >ul >li { + + &:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_02 { + >ul >li { + + &:first-child { + background-image: url(../images/bigdata.jpg); + background-size: contain; + //background-color: green; + } + + >dl > dd{ + + &:nth-child(3) { + &:after { + top: 50%; + } + } + &:nth-child(4) { + &:after { + top: 50%; + } + } + } + }//end of 01 li + }//end of business_01 + + &.business_03 { + >ul >li { + + &:first-child { + background-image: url(../images/soc.jpg); + background-size: contain; + background-repeat: no-repeat; + //background-color: orange; + } + }//end of 01 li + }//end of business_01 + + &.business_04 { + padding-bottom: 100px; + >ul >li { + + &:first-child { + background-image: url(../images/si.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 0 88%; + //background-color: pink; + } + }//end of 01 li + }//end of business_01 + }//end of all div + + }//end of class business +}//end of #business + + +@media screen and(max-width : 768px) {//business_eng 768px 반응형 + + #business_eng { + width: 100%; + + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + height: 50px; + padding-top: 60px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 22px;//변경 + line-height: 1.3em; + font-weight: 600; + margin-bottom: 50px; + + >span {//추가 + display: block; + } + + &:after { + position: absolute; + top: 80px;//변경 + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + width: 90%;//추가 + margin: 0 auto;//추가 + text-align: center; + font-size: 15px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + + >br { + display: none; + } + } + }//end of inner + + >.category { + position: fixed;//추가 + bottom: 0;//추가 + width: 100%; + border-bottom: 1px solid #ddd;//변경 + z-index: 99999; + //ackground-color: green; + + >ul { + margin: 0 auto; + width: 100%;//변경 + + + >li { + float: left;//변경 + width: 25%;//변경 + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px;//변경 + background-color: #eee; + //border-bottom: 1px solid #555; + + color: #555; + cursor: pointer; + + &:last-child { + margin-right: 0; + border-bottom: none; + } + + &:hover { + color:#fff; + background-color: $point-color; + } + + &.on { + color:#fff; + background-color: $point-color; + } + + + }//end of li + }//end of ul + }//end of category + + >.business { + padding-top: 0px;//변경 + width: 100%; + background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + margin-top: 30px;//추가 + + &:first-child { + margin-top: 0; + } + + + >ul { + //background-color: green; + >li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + height: 200px; + float: inherit!important;//추가 + text-indent: -99999px; + + + } + + &:last-child { + height: auto; + margin-top: 20px;//변경 + //background-color: red; + + + >dl{ + width: 90%;//추기 + padding-left: 0px; + margin: 0 auto;//추가 + >dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + >br { + display: none; + } + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.business_01 { + >ul >li { + + &:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_02 { + + >ul >li { + + &:first-child { + + background-image: url(../images/bigdata.jpg); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_03 { + >ul >li { + + &:first-child { + background-image: url(../images/soc.jpg); + background-size: cover; + background-repeat: no-repeat; + //background-color: orange; + } + + &:last-child { + >dl>dt{ + + &:after { + position: absolute; + top: 80px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + } + } + }//end of 01 li + }//end of business_01 + + &.business_04 { + + padding-bottom: 40px;//변경 + >ul >li { + + &:first-child { + background-image: url(../images/si.jpg); + background-size: cover;//변경 + background-repeat: no-repeat; + background-position: 50% 90%; + //background-color: pink; + } + + &:last-child {//추가 + >dl>dt{ + + &:after { + position: absolute; + top: 80px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + } + } + }//end of 01 li + }//end of business_01 + }//end of all div + + }//end of class business + }//end of #business + + +}//business_eng 768px 반응형 + + + +/*contact*/ + +#faq_eng { + position: relative; + width: 100%; + margin-bottom: 60px; + //background-color: green; + height: 600px; + background-color: #fff; + + + >.inner { + width: 1000px; + margin: 0 auto; + + >.faq_info { + float: left; + width: 450px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + + &:last-child { + margin-top: 50px; + font-size: 17px; + //color: $point-color; + font-weight: 600; + } + + >span { + font-size: 20px; + font-weight: 600; + } + + >em { + color: #eee; + } + + &.faq_info_main { + position: relative; + font-size: 29px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + } + }//end of ul + }//end of ceo_info + >.map { + float: right; + margin-top: 50px; + width : 540px; + height : 400px; + border : 0; + + }// end of mobile map + + }//end of inner +}//end of faq + +@media screen and(max-width : 768px) {//faq 768px 반응형 + + + #faq_eng { + position: relative; + width: 100%; + padding-bottom: 60px; + margin-bottom: 0px;//변경 + //background-color: green; + height: auto; + background-color: #fff; + + + >.inner { + width: 100%;//변경 + margin: 0 auto; + + >.faq_info { + float: inherit;//변경 + width: 90%; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + + &:last-child { + border-top: 1px dotted #ddd;//추가 + margin-top: 20px;//변경 + padding-top: 10px;//추가 + font-size: 14px; + color: $point-color; + font-weight: 600; + } + + >span { + font-size: 17px; + font-weight: 600; + } + + >em { + color: #eee; + } + + &.faq_info_main { + position: relative; + text-align: center;//추가 + font-size: 22px;//변경 + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + } + }//end of ul + }//end of ceo_info + >.map { + float: inherit; + width : 100%; + height : 450px; + + background-image: url(../images/map_eng_18.08.06.jpg); + background-position: 10% 50%; + background-size: cover; + border : 0; + + + }//end of map + + }//end of inner + + + }//end of faq + + +}//faq 768px 반응형 + +footer { + width: 100%; + height: 170px; + background-color: #333; + + >.inner { + //background-color: pink; + position: relative; + padding-top: 20px; + + >h1 { + float: left; + margin-left: 40px; + width: 120px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + }//end of h1 + + >address { + float: left; + margin-top: 0px; + margin-left: 30px; + width: 350px; + //background-color: green; + + >ul { + width: 350px; + // background-color: red; + + > li { + + margin-left: 0px; + width: 320px; + //background-color: pink; + text-align: center; + + &:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + margin: 0 auto; + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + + }//end of dt + >dd { + text-align: left; + margin-top: 8px; + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: underline; + } + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of address + + >.f_nav { + float: right; + margin-top: 0px; + width: 200px; + //background-color: blue; + + >ul { + + >li { + float: left; + margin-right: 9px; + padding-right: 11px; + background-image: url(../images/f_right.png); + background-repeat: no-repeat; + background-position: 100% 73%; + + + + &:last-child { + margin-right: none; + background-image: none; + } + + >a { + + font-size: 13px; + color: #fff; + + + } + } + } + + } + + >.copyright { + position: absolute; + top: 120px; + right: -140px; + transform: translateX(-50%); + width: 315px; + font-size: 13px; + letter-spacing: 1px; + color: #fff; + + }//end of copyright + + &:after { + position: absolute; + top: 30px; + left: 180px; + transform: translateX(-50%); + width: 1px; + height: 120px; + background-color: #fff; + content: ''; + }//end of inner:after + + }//end of inner +}//end of footer + + +@media screen and(max-width : 768px) {/*footer 768px 반응형*/ + footer { + width: 100%; + height: auto; + background-color: #333; + + >.inner { + //background-color: pink; + position: relative; + padding-top: 20px; + + >h1 { + float: inherit; + //margin-left: 0px;제거 + margin: 0 auto 180px;//추가 + width: 120px; + height: 40px; + text-indent: -99999px; + background-image: url(../images/logo.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + }//end of h1 + + >.f_left { + float: inherit; + // margin-left: 50px; + margin: 0 auto; + width: 100%;//추가 + //background-color: pink; + + >ul { + width: 100%;//변경 + //background-color: red; + + > li { + + width: 100%;//변경 + //background-color: pink; + //text-align: center; + + &:nth-child(1) dl dt { + // background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + //background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + //background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + display: none; + margin: 0 auto; + width: 100%; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + + }//end of dt + >dd { + padding-left: 20px;//추가 + text-align: left;//변경 + margin-top: 8px; + font-size: 16px;//변경 + font-weight: 500; + line-height: 1.2em; + color: #fff; + + >em { + color: #909090; + } + + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + &:hover { + text-decoration: none;//변경 + } + + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of f_left + + >address { + border-top: 1px solid #666; + float: inherit;//변경 + // margin-top: 0px; + // margin-left: 30px; + margin: 10px 0; + width: 100%;//변경 + //background-color: green; + + >ul { + width: 100%; + // background-color: red; + + > li { + + width: 100%; + //background-color: pink; + text-align: center; + + &:nth-child(1) dl dt { + background-image: url(../images/f_icon_mail.png); + } + + &:nth-child(2) dl dt { + background-image: url(../images/f_icon_tel.png); + } + + &:nth-child(3) dl dt { + background-image: url(../images/f_icon_location.png); + } + + >dl { + >dt { + display: none; + + + }//end of dt + >dd { + padding-left: 25px;//변경 + text-align: left;//변경 + margin-top: 6px;//변경 + font-size: 15px; + font-weight: 500; + line-height: 1.2em; + color: #fff; + + &:nth-child(2) { + font-weight: 700; + } + + &:nth-child(3) { + color: #909090; + } + >a { + font-size: 13px; + color: #909090; + + >span { + display: block; + + >span { + display: block; + } + } + + &:hover { + text-decoration: underline; + } + + + } + + + }//end of dd + }//end of dl + }//end of li + }//end of ul + }//end of address + + >.f_nav { + position: absolute; + top: 75px; + float: inherit;//변경 + margin-top: 0px; + width: 100%;//변경 + //background-color: blue; + + >ul { + + >li { + width: 100%;//추가 + text-align: center;//추가 + float: inherit;//변경 + margin-right: 0px;//변경 + padding-right: 0px;//변경 + background-image: none;//변경 + background-repeat: no-repeat; + background-position: 100% 73%; + border-top: 1px solid #666; + + + + &:last-child { + margin-right: none; + background-image: none; + border-bottom: 1px solid #666; + } + + >a { + display: block; + height: 50px; + line-height: 50px; + font-size: 16px; + color: #fff; + //background-color: orange; + + + } + } + } + + } + + >.copyright { + border-top: 1px solid #666 ;//추가 + position: static; + padding: 20px 0; + top: 10px;//변경 + right: 50%;//변경 + transform: translateX(0); + width: 100%; + font-size: 13px; + letter-spacing: 1px; + text-align: center; + color: #fff; + //background-color: green; + + }//end of copyright + + &:after { + display: none; + + }//end of inner:after 하단 1자 선(상호) + + + }//end of inner + }//end of footer + + +}//footer 768px 반응형 diff --git a/eng/css/reset.css b/eng/css/reset.css new file mode 100644 index 0000000..e2c0eb3 --- /dev/null +++ b/eng/css/reset.css @@ -0,0 +1,48 @@ +@import url(http://fonts.googleapis.com/earlyaccess/nanumgothic.css); + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; + text-decoration: none; + list-style: none; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; + font-family: "Nanum Gothic", sans-serif; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} diff --git a/eng/css/style.css b/eng/css/style.css new file mode 100644 index 0000000..65799d8 --- /dev/null +++ b/eng/css/style.css @@ -0,0 +1,2325 @@ +@charset "UTF-8"; +/*일반현황*/ +.index_tap { + width: 100%; + height: 35px; + border-bottom: 1px solid #eee; + background-color: #ffffff; } + .index_tap > p { + margin: 0 auto; + width: 1000px; + font-size: 13px; + line-height: 35px; + text-align: right; + color: #333; } + .index_tap > p > em { + padding: 0 3px; + font-weight: 900; + color: #ffc700; } + .index_tap > p > span > a { + color: #222; + font-weight: 900; } + .index_tap > p > span > a:hover { + text-decoration: underline; } + +@media screen and (max-width: 768px) { + /*index_tap 768px 반응형*/ + .index_tap { + width: 100%; + height: 35px; + border-bottom: 1px solid #eee; + background-color: #ffffff; } + .index_tap > p { + margin: 0 auto; + width: 100%; + font-size: 13px; + line-height: 35px; + text-align: center; + color: #333; } + .index_tap > p > em { + padding: 0 3px; + font-weight: 900; + color: #ffc700; } + .index_tap > p > span > a { + padding-right: 240px; + color: #222; + font-weight: 900; } + .index_tap > p > span > a:hover { + text-decoration: underline; } } +.index_tap2 { + background-color: transparent; + border-bottom: 1px solid #e1e1e1; } + +#status { + width: 100%; + margin-bottom: 60px; + height: 1350px; + background-color: #fff; } + #status > .status { + position: relative; + width: 1000px; + margin: 0 auto 100px; } + #status > .status > ul { + margin-top: 60px; + width: 100%; } + #status > .status > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #status > .status > ul > li.status_info_main { + position: relative; + font-size: 20px; + font-weight: 700; + color: #1e3571; + margin-bottom: 70px; + line-height: 1.3em; } + #status > .status > ul > li.status_info_main:after { + position: absolute; + top: 85px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #status > .status > ul > li > em { + color: #eee; } + #status > .status > ul > li > span { + font-size: 20px; } + #status > .status > ol { + margin-top: 50px; + color: #bbb; + line-height: 1.4em; } + #status > .status > ol > li { + font-size: 13px; } + #status > .status > ol > li:first-child { + font-size: 18px; + margin-bottom: 10px; } + #status > .status:after { + position: absolute; + top: 120px; + right: 0; + width: 260px; + height: 345px; + background-image: url(../images/company_3.png); + background-repeat: no-repeat; + background-position: 0 100%; + background-size: contain; + content: ''; } + #status > .organiz { + width: 100%; + height: 700px; } + #status > .organiz > .inner { + position: relative; + width: 1000px; + height: 600px; } + #status > .organiz > .inner > h2 { + width: 1000px; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: #1e3571; + margin-bottom: 0px; } + #status > .organiz > .inner > .orgimg { + width: 100%; + height: 100%; + background-image: url(../images/organiz.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; } + #status > .organiz > .inner:after { + position: absolute; + top: 65px; + width: 1000px; + height: 1px; + background-color: #ddd; + content: ''; } + #status > .organiz > .org_eng { + position: relative; + width: 1000px; + height: 600px; + background-image: url(../images/organiz_eng.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; } + #status > .organiz > .org_eng > h2 { + width: 1000px; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: #1e3571; + margin-bottom: 0px; } + #status > .organiz > .org_eng:after { + position: absolute; + top: 65px; + width: 1000px; + height: 1px; + background-color: #ddd; + content: ''; } + +@media screen and (max-width: 768px) { + #status { + width: 100%; + margin-bottom: 0px; + padding-bottom: 60px; + height: auto; + background-color: #fff; } + #status > .status { + position: relative; + width: 90%; + padding-bottom: 50px; + margin: 0 auto 0px; } + #status > .status > ul { + margin-top: 60px; + width: 100%; } + #status > .status > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #status > .status > ul > li.status_info_main { + position: relative; + font-size: 20px; + font-weight: 700; + color: #1e3571; + margin-bottom: 70px; + line-height: 1.3em; } + #status > .status > ul > li.status_info_main > br { + display: none; } + #status > .status > ul > li.status_info_main:after { + position: absolute; + top: 85px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #status > .status > ul > li > em { + color: #eee; } + #status > .status > ul > li > span { + font-size: 20px; } + #status > .status > ol { + margin-top: 50px; + color: #bbb; + line-height: 1.4em; } + #status > .status > ol > li { + font-size: 13px; } + #status > .status > ol > li:first-child { + font-size: 18px; + margin-bottom: 10px; } + #status > .status:after { + display: none; + position: absolute; + top: 120px; + right: 0; + width: 260px; + height: 345px; + background-image: url(../images/company_3.png); + background-repeat: no-repeat; + background-position: 0 100%; + background-size: contain; + content: ''; } + #status > .organiz { + width: 100%; + height: 400px; } + #status > .organiz > .inner { + position: relative; + width: 350px; + height: 350px; + background-image: none; } + #status > .organiz > .inner > h2 { + width: 100%; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: #1e3571; + margin-bottom: 0px; } + #status > .organiz > .inner > .orgimg_kr { + width: 100%; + background-image: url(../images/organiz_kor_m.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; } + #status > .organiz > .inner > .orgimg_eng { + width: 100%; + background-image: url(../images/organiz_m.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; } + #status > .organiz > .inner:after { + position: absolute; + top: -30px; + left: 50%; + transform: translateX(-50%); + width: 90%; + height: 1px; + background-color: #ddd; + content: ''; } + #status > .organiz > .org_eng { + width: 100%; + height: 400px; } + #status > .organiz > .org_eng > h2 { + width: 100%; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: #1e3571; + margin-bottom: 0px; } + #status > .organiz > .org_eng:after { + position: absolute; + top: -25px; + width: 90%; + height: 1px; + background-color: #ddd; + content: ''; } } +/*연혁*/ +#since { + width: 100%; + margin-bottom: 60px; + background-color: #fff; } + #since > .since { + position: relative; + width: 1000px; + margin: 0 auto; } + #since > .since > ul { + margin-top: 80px; + width: 100%; } + #since > .since > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #since > .since > ul > li.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ } + #since > .since > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #since > .since > ul > li > em { + color: #ffc700; } + #since > .since > ul > li > span { + font-size: 20px; } + #since > .since > .since_info { + width: 100%; } + #since > .since > .since_info > h2 { + padding-left: 100px; + font-size: 50px; + font-weight: 500; + font-style: italic; + letter-spacing: -4px; + color: #eee; } + #since > .since > .since_info > div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; } + #since > .since > .since_info > div > ul { + padding-left: 150px; + width: 100%; } + #since > .since > .since_info > div > ul > li { + float: left; + margin-left: 230px; + line-height: 2.5em; } + #since > .since > .since_info > div > ul > li:first-child { + font-size: 40px; + font-weight: 900; + color: #ddd; } + #since > .since > .since_info > div > ul > li > dl { + padding: 5px 10px; + width: 100%; } + #since > .since > .since_info > div > ul > li > dl > dd { + position: relative; + font-size: 16px; + font-weight: 600; } + #since > .since > .since_info > div > ul > li > dl > dd:after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: -20px; + width: 10px; + height: 10px; + border-radius: 15px; + background-color: #ffc700; + content: ''; } + +@media screen and (max-width: 768px) { + /*since 768px 반응형*/ + #since { + width: 100%; + margin-bottom: 0px; + padding-bottom: 80px; + height: auto; + background-color: #fff; } + #since > .since { + position: relative; + width: 90%; + margin: 0 auto; } + #since > .since > ul { + margin-top: 80px; + width: 100%; } + #since > .since > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #since > .since > ul > li.status_info_main { + position: relative; + font-size: 22px; + font-weight: 600; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ } + #since > .since > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #since > .since > ul > li > em { + color: #ffc700; } + #since > .since > ul > li > span { + font-size: 20px; } + #since > .since > .since_info { + width: 100%; } + #since > .since > .since_info > h2 { + padding-bottom: 20px; + padding-left: 0px; + font-size: 50px; + font-weight: 500; + font-style: italic; + letter-spacing: -4px; + color: #eee; } + #since > .since > .since_info > div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; } + #since > .since > .since_info > div > ul { + padding-left: 0px; + width: 100%; } + #since > .since > .since_info > div > ul > li { + float: inherit; + margin-left: 0px; + line-height: 1.45em; } + #since > .since > .since_info > div > ul > li:first-child { + display: none; + font-size: 40px; + font-weight: 900; + color: #ddd; } + #since > .since > .since_info > div > ul > li > dl { + padding: 5px 0px; + width: 100%; } + #since > .since > .since_info > div > ul > li > dl > dd { + position: relative; + font-size: 14px; + font-weight: 500; + padding-bottom: 10px; } + #since > .since > .since_info > div > ul > li > dl > dd:after { + position: absolute; + top: 11px; + transform: translateY(-50%); + left: -10px; + width: 5px; + height: 5px; + border-radius: 15px; + background-color: #ffc700; + content: ''; } } +/*보유인증현황*/ +#certificate { + width: 100%; + margin-bottom: 0 auto; + height: 1700px; + background-color: #fff; } + #certificate > .certificate { + position: relative; + width: 1000px; + margin: 0 auto; } + #certificate > .certificate > ul { + margin-top: 80px; + width: 100%; } + #certificate > .certificate > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #certificate > .certificate > ul > li.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #certificate > .certificate > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #certificate > .certificate > ul > li > em { + color: #ddd; } + #certificate > .certificate > ul > li > span { + font-size: 20px; } + #certificate > .certificate > .certificate_info { + width: 100%; } + #certificate > .certificate > .certificate_info > div { + width: 100%; } + #certificate > .certificate > .certificate_info > div > ul > li { + float: left; + margin: 0 47px 50px 0; + width: 300px; + height: 400px; + border: 1px dotted #eee; } + #certificate > .certificate > .certificate_info > div > ul > li:last-child { + margin-right: 0; } + #certificate > .certificate > .certificate_info > div > ul > li > dl > dt { + width: 300px; + height: 350px; + text-indent: -99999px; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + #certificate > .certificate > .certificate_info > div > ul > li > dl > dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_10.png); + background-position: 50% 50%; } + +@media screen and (max-width: 768px) { + /*certificate 768px 반응형*/ + #certificate { + width: 100%; + margin-bottom: 0 auto 0; + height: auto; + background-color: #fff; } + #certificate > .index_tap > p > span > a { + padding-right: 240px; } + #certificate > .certificate { + position: relative; + width: 100%; + margin: 0 auto; } + #certificate > .certificate > ul { + margin-top: 80px; + width: 100%; } + #certificate > .certificate > ul > li { + width: 100%; + text-align: center; + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #certificate > .certificate > ul > li.status_info_main { + position: relative; + font-size: 22px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #certificate > .certificate > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #certificate > .certificate > ul > li > em { + color: #ddd; } + #certificate > .certificate > ul > li > span { + font-size: 20px; } + #certificate > .certificate > .certificate_info { + width: 100%; } + #certificate > .certificate > .certificate_info > div { + width: 100%; } + #certificate > .certificate > .certificate_info > div > ul { + width: 100%; } + #certificate > .certificate > .certificate_info > div > ul > li { + float: inherit; + margin: 0 0px 50px 0; + width: 100%; + height: 400px; + border: 1px dotted #eee; + border-top: none; + border-left: none; + border-right: none; } + #certificate > .certificate > .certificate_info > div > ul > li:last-child { + margin-right: 0; } + #certificate > .certificate > .certificate_info > div > ul > li > dl > dt { + width: 100%; + height: 350px; + text-indent: -99999px; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; } + #certificate > .certificate > .certificate_info > div > ul > li > dl > dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_10.png); + background-position: 50% 50%; } } +/* +#research { + width: 100%; + height: 3500px; + margin-bottom: 0 auto; + //background-color: green; + background-color: #fff; + background-image: url(../images/bus_bg.jpg); + background-repeat: repeat-Y; + + .research { + width: 100%; + height: 400px; + margin-bottom: 40px; + background-color: #fff; + + + >.inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + }//end of class research + + .inner { + + + >.rndSys { + width: 100%; + //background-color: green; + + >.camera { + margin: 0 auto; + width: 900px; + height: 600px; + background-image: url(../images/camera.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + }//end of camera + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + + } + + } + }//ednd of ul + + .rndSys_info { + padding-top: 10px; + line-height: 1.5em; + color: #aaa; + cursor: default; + }//end of rndSys_info + }//end of rndSys + + + + .strength { + margin-top: 150px; + width: 100%; + + >.strength_box1 { + float: left; + width: 870px; + height: 560px; + //background-color: orange; + + >ul { + padding: 50px 0 0 30px; + //background-color: orange; + + >li { + float: left; + + + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >.strength_top { + margin-top: 50px; + padding-left: 30px; + width: 870px; + height: 200px; + //background-color: green; + + >ul { + >li { + float: left; + width: 415px; + height: 200px; + + &:first-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_01.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_터널 유고영상 빅데이터 확보 + + &:last-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_02.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_현존하는 시스템의 한계극복기능 + + >dl { + width: 100%; + + >dt { + width: 415px; + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {//아이콘의 공통 스타일 + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + }//end of first-child + + &:last-child {//아이콘 옆 글자 + + >dl { + padding-left: 15px; + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 10px 0; + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_top + + >.strength_bot { + padding-left: 30px; + width: 870px; + height: 200px; + //background-color: green; + + >ul { + >li { + float: left; + width: 415px; + height: 200px; + + &:first-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_03.png); + }//우수한 경제성 아이콘 + + }//end of ul li:first-child_우수한 경제성 아이콘 + + &:last-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_04.png); + }//지속적인 기술력 성장 아이콘 + + }//end of ul li:first-child_속적인 기술력 성장 아이콘 + + >dl { + width: 100%; + + >dt { + width: 415px; + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {//아이콘의 공통 스타일 + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + }//end of first-child + + &:last-child {//아이콘 옆 글자 + + >dl { + padding-left: 15px; + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 10px 0; + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_bot + + }//end of strength_box1 + + >.strength_box2 { + float: left; + width: 330px; + height: 560px; + background-image: url(../images/strength.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 0; + + }//end of strength_box2 + + + }//end of strength + + + >.rnd_schedule { + width: 100%; + margin-top: 150px; + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//end of ul + + >.schedule_content { + margin-top: 30px; + + >ul { + width: 1000px; + height: 70px; + margin-bottom: 10px; + //background-color: orange; + + >li { + float: left; + + &:first-child { + width: 270px; + height: 100%; + background-color: #1e3571; + text-align: center; + font-size: 16px; + font-weight: 600; + line-height: 70px; + color: #fff; + cursor: default; + }//end of 스케쥴 제목 + + &:last-child { + width: 730px; + height: 100%; + border: 1px solid #1e3571; + box-sizing: border-box; + padding: 30px; + font-size: 16px; + font-weight: 600; + line-height: 10px; + cursor: default; + transition-duration: .2s; + + >em { + opacity: 0; + } + }//end of 스케쥴 제목 + + }//end of li + }//end of ul + }//end of schedule_content + + + + + }//end of rnd_schedule + + + >.rnd_outside { + width: 100%; + margin-top: 150px; + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >ol { + margin-top: 30px; + width: 100%; + + >li { + float: left; + width: 300px; + height: 570px; + background-repeat: no-repeat; + background-size: cover; + + &:nth-child(1) { + background-image: url(../images/thief.png); + background-position:24% 50%; + } + &:nth-child(2) { + background-image: url(../images/lamp.jpg); + background-position:60% 50%; + } + &:nth-child(3) { + background-image: url(../images/auto_btn.png); + background-position:50% 50%; + } + &:nth-child(4) { + background-image: url(../images/hemet.jpg); + background-position:45% 50%; + } + + >dl { + opacity: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.6); + color: #fff; + text-align: center; + cursor: default; + + >dt { + position: relative; + padding-top: 150px; + font-size: 25px; + + &:after { + position: absolute; + top: 190px; + left: 50%; + transform: translateX(-50%); + width: 20px; + height: 1px; + background-color: #fff; + content: ''; + } + } + + >dd { + padding: 30px 30px 0 30px; + font-size: 14px; + text-align: center; + line-height: 1.6em; + } + } + }//end of li + } + + }//end of rnd_outside + }//end of inner + +}//end of #research + +//연구개발 모바일버전 + +@media screen and(max-width : 768px) { + #research { + width: 100%; + height: auto;//m + margin-bottom: 0 auto; + //background-color: green; + background-color: #fff; + background-image: url(../images/bus_bg.jpg); + background-repeat: repeat-Y; + + .research { + width: 100%; + height: 400px; + margin-bottom: 40px; + background-color: #fff; + + + >.inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + }//end of class research + + .inner { + + + >.rndSys { + width: 100%; + //background-color: green; + + >.camera { + margin: 0 auto; + width: 100%;//m + height: 300px;//m + background-image: url(../images/camera.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain;//m + }//end of camera + + >ul { + //background-color: orange; + + >li { + float: inherit;//m + + &:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px;//m + + } + &:last-child { + display: none;//m + font-size: 16px; + padding-top: 5px;//m + padding-left: 10px;//m + padding-right: 10px;//m + + } + + } + }//ednd of ul + + .rndSys_info { + padding-top: 10px; + padding: 10px;//m + line-height: 1.5em; + color: #aaa; + cursor: default; + }//end of rndSys_info + }//end of rndSys + + + + .strength { + margin-top: 50px;//m + width: 100%; + + >.strength_box1 { + float: inherit;//m + width: 100%;//m + height: 560px; + //background-color: orange; + + >ul { + padding: 0px 0 0 0px;//m + //background-color: orange; + + >li { + float: inherit;//m + + &:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px;//m + } + &:last-child { + display: none;//m + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >.strength_top { + margin-top: 30px;//m + padding-left: 0px;//m + padding-right: 0px;//m + width: 100%;//m + height: 170px;//m + + //background-color: green; + + >ul { + >li { + float: left; + width: 100%; + height: 170px; + border-bottom: 1px dashed #ccc; + + &:first-child { + height: 160px;//m + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_01.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_터널 유고영상 빅데이터 확보 + + &:last-child { + padding-top: 50px;//m + height: 200px;//m + + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_02.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_현존하는 시스템의 한계극복기능 + + >dl { + width: 100%; + + >dt { + width: 100%;//m + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {//아이콘의 공통 스타일 + width: 40px; + height: 40px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + margin-left: 10px;//m + }//end of first-child + + &:last-child {//아이콘 옆 글자 + + >dl { + padding-left: 10px;//m + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 0px 0;//m + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 0px 0 0 10px;//m + font-size: 15px; + line-height: 1.45em; + color: #333; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_top + + >.strength_bot { + padding-left: 0px;//m + padding-right: 0px;//m + width: 100%;//m + height: 200px; + //background-color: green; + + + >ul { + >li { + float: left; + width: 100%; + height: 200px; + border-bottom: 1px dashed #ccc; + + &:first-child { + padding-top: 50px;//m + height: 160px;//m + + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_03.png); + }//우수한 경제성 아이콘 + + }//end of ul li:first-child_우수한 경제성 아이콘 + + &:last-child { + padding-top: 50px;//m + height: 160px;//m + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_04.png); + }//지속적인 기술력 성장 아이콘 + + }//end of ul li:first-child_속적인 기술력 성장 아이콘 + + >dl { + width: 100%; + + >dt { + width: 100%;//m + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {//아이콘의 공통 스타일 + width: 40px; + height: 40px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + margin-left: 10px;//m + }//end of first-child + + &:last-child {//아이콘 옆 글자 + + >dl { + padding-left: 10px;//m + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 0px 0;//m + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 0px 0 0 10px;//m + font-size: 15px; + line-height: 1.45em; + color: #333; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_bot + + }//end of strength_box1 + + >.strength_box2 { + display: none;//m + float: left; + width: 330px; + height: 560px; + background-image: url(../images/strength.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 0; + + }//end of strength_box2 + + + }//end of strength + + + >.rnd_schedule { + width: 100%; + margin-top: 80px;//m + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px;//m + } + &:last-child { + display: none;//m + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//end of ul + + >.schedule_content { + width: 100%;//m + margin-top: 30px; + + >ul { + width: 90%; + height: auto;//m + //margin-bottom: 10px; + margin: 0 auto 10px;//m + //background-color: orange; + + >li { + float: inherit;//m + + &:first-child { + width: 100%; + height: 100%; + background-color: #1e3571; + text-align: center; + font-size: 16px; + font-weight: 600; + line-height: 70px; + color: #fff; + cursor: default; + }//end of 스케쥴 제목 + + &:last-child { + width: 100%; + height: 100%; + border: 1px solid #1e3571; + box-sizing: border-box; + padding: 30px; + font-size: 16px; + font-weight: 600; + line-height: 1.45em;//m + cursor: default; + transition-duration: .2s; + + >em { + opacity: 0; + } + }//end of 스케쥴 제목 + + }//end of li + }//end of ul + }//end of schedule_content + + + + + }//end of rnd_schedule + + + >.rnd_outside { + width: 100%; + margin-top: 80px;//m + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px;//m + } + &:last-child { + display: none;//m + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >ol { + margin-top: 30px; + width: 100%; + + >li { + float: left; + width: 100%;//m + height: 200px;//m + background-repeat: no-repeat; + background-size: cover; + + &:nth-child(1) { + background-image: url(../images/thief.png); + background-position:24% 50%; + } + &:nth-child(2) { + background-image: url(../images/lamp.jpg); + background-position:60% 50%; + } + &:nth-child(3) { + background-image: url(../images/auto_btn.png); + background-position:50% 50%; + } + &:nth-child(4) { + background-image: url(../images/hemet.jpg); + background-position:45% 50%; + } + + >dl { + opacity: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.6); + color: #fff; + text-align: center; + cursor: default; + + >dt { + position: relative; + padding-top: 50px;//m + font-size: 25px; + + &:after { + position: absolute; + top: 90px; + left: 50%; + transform: translateX(-50%); + width: 20px; + height: 1px; + background-color: #fff; + content: ''; + } + } + + >dd { + padding: 30px 30px 0 30px; + font-size: 14px; + text-align: center; + line-height: 1.6em; + text-align: center;//m + } + } + }//end of li + } + + }//end of rnd_outside + }//end of inner + + }//end of #research + +}//end of research 모바일 +*/ +#research { + width: 100%; + background-color: white; } + #research > .inner { + width: 100%; + height: 180px; + padding-top: 60px; + margin: 0 auto; + background-image: url(../images/research_m01.jpg); } + #research > .inner > h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + color: #fff; } + #research > .inner > h2:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #research > .inner > .threeTap { + width: 100%; } + #research > .inner > .threeTap ul { + width: 960px; + margin: 0 auto; } + #research > .inner > .threeTap ul > li { + display: block; + float: left; + margin: 0 20px; + font-size: 20px; + font-weight: 600; + color: #fff; + cursor: default; } + #research > .research { + padding-top: 130px; + margin-bottom: 100px; + width: 100%; } + #research > .research > div { + width: 100%; } + #research > .research > div > ul > li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #research > .research > div > ul > li:first-child { + text-indent: -99999px; } + #research > .research > div > ul > li:last-child { + height: 240px; + margin-top: 120px; } + #research > .research > div > ul > li:last-child > dl { + padding-left: 100px; } + #research > .research > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 40px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #research > .research > div > ul > li:last-child > dl > dt:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #research > .research > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #1e3571; + font-weight: 500; } + #research > .research > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #research > .research > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #1e3571; + border-radius: 7px; + content: ''; } + #research > .research > div.research_01 > ul > li:first-child { + background-image: url(../images/camera.png); + background-size: contain; } + #research > .research > div.research_02 { + width: 100%; + height: 100%; + background-image: url(../images/bg_2.png); } + #research > .research > div.research_02 > ul > li > dl dt { + color: #fff; } + #research > .research > div.research_02 > ul > li > dl dd { + color: #fff; } + #research > .research > div.research_02 > ul > li:first-child { + background-image: url(../images/crack.png); + background-size: contain; } + #research > .research > div.research_03 > ul > li:first-child { + background-image: url(../images/moon.png); + background-size: contain; + background-repeat: no-repeat; } + +@media screen and (max-width: 768px) { + #research { + width: 100%; + background-color: white; } + #research > .inner { + height: 180px; + padding-top: 30px; + margin: 0 auto; + background-image: url(../images/research_m01.jpg); } + #research > .inner > h2 { + position: relative; + text-align: center; + font-size: 22px; + font-weight: 600; + margin-bottom: 50px; } + #research > .inner > h2:after { + position: absolute; + top: 50px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #research > .inner > .threeTap { + width: 100%; + height: 100%; } + #research > .inner > .threeTap ul { + width: 100%; + margin: 0 auto; } + #research > .inner > .threeTap ul > li { + display: block; + float: inherit; + text-align: center; + margin: 10px 20px; + font-size: 20px; + font-weight: 600; + color: #fff; + cursor: default; } + #research > .category { + position: fixed; + bottom: 0; + width: 100%; + border-bottom: 1px solid #ddd; + z-index: 99999; } + #research > .category > ul { + margin: 0 auto; + width: 100%; } + #research > .category > ul > li { + float: left; + width: 25%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px; + background-color: #eee; + color: #555; + cursor: pointer; } + #research > .category > ul > li:last-child { + margin-right: 0; + border-bottom: none; } + #research > .category > ul > li:hover { + color: #fff; + background-color: #1e3571; } + #research > .category > ul > li.on { + color: #fff; + background-color: #1e3571; } + #research > .research { + padding-top: 0px; + width: 100%; + background-image: url(../images/bus_bg.jpg); } + #research > .research > div { + width: 100%; + margin-top: 30px; } + #research > .research > div:first-child { + margin-top: 0; } + #research > .research > div > ul > li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #research > .research > div > ul > li:first-child { + height: 200px; + float: inherit !important; + text-indent: -99999px; } + #research > .research > div > ul > li:last-child { + height: auto; + margin-top: 20px; } + #research > .research > div > ul > li:last-child > dl { + width: 90%; + padding-left: 0px; + margin: 0 auto; } + #research > .research > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #research > .research > div > ul > li:last-child > dl > dt:after { + display: none; + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #research > .research > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #1e3571; + font-weight: 500; } + #research > .research > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #research > .research > div > ul > li:last-child > dl > dd > br { + display: none; } + #research > .research > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #1e3571; + border-radius: 7px; + content: ''; } + #research > .research > div.research_01 > ul > li:first-child { + background-image: url(../images/camera.png); + background-size: contain; } + #research > .research > div.research_02 { + width: 100%; + height: 100%; + background-image: url(../images/bg_2.png); } + #research > .research > div.research_02 > ul > li > dl dt { + color: #fff; } + #research > .research > div.research_02 > ul > li > dl dd { + color: #fff; } + #research > .research > div.research_02 > ul > li:first-child { + background-image: url(../images/crack.png); + background-size: contain; } + #research > .research > div.research_03 > ul > li:first-child { + background-image: url(../images/moon.png); + background-size: contain; + background-repeat: no-repeat; } } +/*사업영역*/ +#business { + width: 100%; + background-color: white; } + #business > .inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; } + #business > .inner > h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; } + #business > .inner > h2:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #business > .inner p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; } + #business > .category { + width: 100%; + border-bottom: 1px solid #eee; } + #business > .category > ul { + margin: 0 auto; + width: 850px; } + #business > .category > ul > li { + float: left; + width: 24%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 3px; + background-color: #ddd; + color: #555; + cursor: pointer; } + #business > .category > ul > li:last-child { + margin-right: 0; } + #business > .category > ul > li:hover { + color: #fff; + background-color: #1e3571; } + #business > .category > ul > li.on { + color: #fff; + background-color: #1e3571; } + #business > .business { + padding-top: 130px; + width: 100%; + background-image: url(../images/bus_bg.jpg); } + #business > .business > div { + width: 100%; } + #business > .business > div > ul > li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #business > .business > div > ul > li:first-child { + text-indent: -99999px; } + #business > .business > div > ul > li:last-child { + height: 240px; + margin-top: 120px; } + #business > .business > div > ul > li:last-child > dl { + padding-left: 100px; } + #business > .business > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 40px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #business > .business > div > ul > li:last-child > dl > dt:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #business > .business > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #1e3571; + font-weight: 500; } + #business > .business > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #business > .business > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #1e3571; + border-radius: 7px; + content: ''; } + #business > .business > div.business_01 > ul > li:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; } + #business > .business > div.business_02 > ul > li:first-child { + background-image: url(../images/bigdata.jpg); + background-size: contain; } + #business > .business > div.business_03 > ul > li:first-child { + background-image: url(../images/soc.jpg); + background-size: contain; + background-repeat: no-repeat; } + #business > .business > div.business_04 { + padding-bottom: 100px; } + #business > .business > div.business_04 > ul > li:first-child { + background-image: url(../images/si.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 0 88%; } + +@media screen and (max-width: 768px) { + #business { + width: 100%; + background-color: white; } + #business > .inner { + height: 50px; + padding-top: 60px; + margin: 0 auto 130px; } + #business > .inner > h2 { + position: relative; + text-align: center; + font-size: 22px; + font-weight: 600; + margin-bottom: 50px; } + #business > .inner > h2:after { + position: absolute; + top: 50px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #business > .inner p { + text-align: center; + font-size: 15px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; } + #business > .category { + position: fixed; + bottom: 0; + width: 100%; + border-bottom: 1px solid #ddd; + z-index: 99999; } + #business > .category > ul { + margin: 0 auto; + width: 100%; } + #business > .category > ul > li { + float: left; + width: 25%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px; + background-color: #eee; + color: #555; + cursor: pointer; } + #business > .category > ul > li:last-child { + margin-right: 0; + border-bottom: none; } + #business > .category > ul > li:hover { + color: #fff; + background-color: #1e3571; } + #business > .category > ul > li.on { + color: #fff; + background-color: #1e3571; } + #business > .business { + padding-top: 0px; + width: 100%; + background-image: url(../images/bus_bg.jpg); } + #business > .business > div { + width: 100%; + margin-top: 30px; } + #business > .business > div:first-child { + margin-top: 0; } + #business > .business > div > ul > li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #business > .business > div > ul > li:first-child { + height: 200px; + float: inherit !important; + text-indent: -99999px; } + #business > .business > div > ul > li:last-child { + height: auto; + margin-top: 20px; } + #business > .business > div > ul > li:last-child > dl { + width: 90%; + padding-left: 0px; + margin: 0 auto; } + #business > .business > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #business > .business > div > ul > li:last-child > dl > dt:after { + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #business > .business > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #1e3571; + font-weight: 500; } + #business > .business > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #business > .business > div > ul > li:last-child > dl > dd > br { + display: none; } + #business > .business > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #1e3571; + border-radius: 7px; + content: ''; } + #business > .business > div.business_01 > ul > li:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; } + #business > .business > div.business_02 > ul > li:first-child { + background-image: url(../images/bigdata.jpg); + background-size: contain; } + #business > .business > div.business_03 > ul > li:first-child { + background-image: url(../images/soc.jpg); + background-size: cover; + background-repeat: no-repeat; } + #business > .business > div.business_04 { + padding-bottom: 40px; } + #business > .business > div.business_04 > ul > li:first-child { + background-image: url(../images/si.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 90%; } } +#faq { + position: relative; + width: 100%; + margin-bottom: 60px; + height: 550px; + background-color: #fff; } + #faq > .inner { + width: 1000px; + margin: 0 auto; } + #faq > .inner > .faq_info { + float: left; + width: 450px; + margin: 0 auto; } + #faq > .inner > .faq_info > ul { + margin-top: 80px; + width: 100%; } + #faq > .inner > .faq_info > ul > li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; } + #faq > .inner > .faq_info > ul > li:last-child { + margin-top: 50px; + font-size: 17px; + color: #1e3571; + font-weight: 600; } + #faq > .inner > .faq_info > ul > li > span { + font-size: 20px; + font-weight: 600; } + #faq > .inner > .faq_info > ul > li > em { + color: #eee; } + #faq > .inner > .faq_info > ul > li.faq_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #faq > .inner > .faq_info > ul > li.faq_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #faq > .inner > .map { + float: right; + margin-top: 50px; + width: 540px; + height: 400px; + border: 0; } + +@media screen and (max-width: 768px) { + #faq { + position: relative; + width: 100%; + padding-bottom: 60px; + margin-bottom: 0px; + height: auto; + background-color: #fff; } + #faq > .inner { + width: 100%; + margin: 0 auto; } + #faq > .inner > .faq_info { + float: inherit; + width: 90%; + margin: 0 auto; } + #faq > .inner > .faq_info > ul { + margin-top: 80px; + width: 100%; } + #faq > .inner > .faq_info > ul > li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; } + #faq > .inner > .faq_info > ul > li:last-child { + border-top: 1px dotted #ddd; + margin-top: 20px; + padding-top: 10px; + font-size: 14px; + color: #1e3571; + font-weight: 600; } + #faq > .inner > .faq_info > ul > li > span { + font-size: 17px; + font-weight: 600; } + #faq > .inner > .faq_info > ul > li > em { + color: #eee; } + #faq > .inner > .faq_info > ul > li.faq_info_main { + position: relative; + text-align: center; + font-size: 22px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #faq > .inner > .faq_info > ul > li.faq_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #faq > .inner > .map { + float: inherit; + margin-top: 20px; + width: 100%; + height: 400px; + border: 0; } } +/*반응형*/ +.pos_right { + background-color: red; } + .pos_right > dl > dt:after { + left: 200px; } + +/*# sourceMappingURL=style.css.map */ diff --git a/eng/css/style.css.map b/eng/css/style.css.map new file mode 100644 index 0000000..28f98ed --- /dev/null +++ b/eng/css/style.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["style.scss"], +"names": [], +"file": "style.css" +} \ No newline at end of file diff --git a/eng/css/style.scss b/eng/css/style.scss new file mode 100644 index 0000000..0594c01 --- /dev/null +++ b/eng/css/style.scss @@ -0,0 +1,3237 @@ +$point-color : #1e3571; +$point-color2 : #ffc700; + +/*일반현황*/ + +.index_tap { + width: 100%; + height: 35px; + border-bottom : 1px solid #eee; + background-color: #ffffff; + + >p { + margin: 0 auto; + width: 1000px; + font-size: 13px; + line-height: 35px; + text-align: right; + color: #333; + + >em { + padding: 0 3px; + font-weight: 900; + color: $point-color2; + + } + >span { + + >a { + color: #222; + font-weight: 900; + + &:hover { + text-decoration: underline; + } + } + } + }//end of p +}//end of index_tap + +@media screen and(max-width : 768px) {/*index_tap 768px 반응형*/ + + + .index_tap { + width: 100%; + height: 35px; + border-bottom : 1px solid #eee; + background-color: #ffffff; + + >p { + margin: 0 auto; + width: 100%; + font-size: 13px; + line-height: 35px; + text-align: center;//변경 + color: #333; + + >em { + padding: 0 3px; + font-weight: 900; + color: $point-color2; + + } + >span { + + >a { + padding-right: 240px;//추가 + color: #222; + font-weight: 900; + + &:hover { + text-decoration: underline; + } + } + } + }//end of p + }//end of index_tap + + + +}//index_tap 768px 반응형 + +.index_tap2 { + background-color: transparent; + border-bottom: 1px solid #e1e1e1; +} + +#status { + width: 100%; + margin-bottom: 60px; + //background-color: green; + height: 1350px; + background-color: #fff; + + + >.status { + position: relative; + width: 1000px; + margin: 0 auto 100px; + + >ul { + margin-top: 60px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 20px; + font-weight: 700; + color: $point-color; + margin-bottom: 70px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 85px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #eee; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >ol { + margin-top: 50px; + color: #bbb; + line-height: 1.4em; + + >li{ + + font-size: 13px; + + &:first-child { + font-size: 18px; + margin-bottom: 10px; + } + }//end of li + }//end of ol + + &:after { + position: absolute; + top: 120px; + right: 0; + width: 260px; + height: 345px; + + background-image: url(../images/company_3.png); + background-repeat: no-repeat; + background-position: 0 100%; + background-size: contain; + content: ''; + } + }//end of status + + >.organiz { + width: 100%; + height: 700px; + //background-color: ; + + + + >.inner { + position: relative; + width: 1000px; + height: 600px; + + + >h2 { + width: 1000px; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: $point-color; + margin-bottom:0px; + } + + >.orgimg { + width: 100%; + height: 100%; + background-image: url(../images/organiz.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; + } + + &:after { + position: absolute; + top : 65px; + width: 1000px; + height: 1px; + background-color: #ddd; + content: ''; + } + } + + >.org_eng { + position: relative; + width: 1000px; + height: 600px; + background-image: url(../images/organiz_eng.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; + + >h2 { + width: 1000px; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: $point-color; + margin-bottom:0px; + } + + &:after { + position: absolute; + top : 65px; + width: 1000px; + height: 1px; + background-color: #ddd; + content: ''; + } + } + }//end of organiz + + + +}//end of status + + +@media screen and(max-width : 768px) { //status 768px 반응형 + + #status { + width: 100%; + margin-bottom: 0px;//변경 + padding-bottom: 60px; + //background-color: green; + height: auto; + background-color: #fff; + + + >.status { + position: relative; + width: 90%;//변경 + padding-bottom: 50px;//c추가 + margin: 0 auto 0px;//변경 + + >ul { + margin-top: 60px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 20px; + font-weight: 700; + color: $point-color; + margin-bottom: 70px; + line-height: 1.3em; + + >br { + display: none; + } + + &:after { + position: absolute; + top: 85px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #eee; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >ol { + margin-top: 50px; + color: #bbb; + line-height: 1.4em; + + >li{ + + font-size: 13px; + + &:first-child { + font-size: 18px; + margin-bottom: 10px; + } + }//end of li + }//end of ol + + &:after { + display: none; + position: absolute; + top: 120px; + right: 0; + width: 260px; + height: 345px; + + background-image: url(../images/company_3.png); + background-repeat: no-repeat; + background-position: 0 100%; + background-size: contain; + content: ''; + } + }//end of status + + >.organiz { + //display: none; + width: 100%; + height: 400px; + //background-color: ; + + + + >.inner { + position: relative; + width: 350px;//변경 + height: 350px;//변경 + background-image: none;//추가 + + + >h2 { + width: 100%;//변경 + margin: 0 auto; + text-align: left; + font-size: 25px; + color: $point-color; + margin-bottom:0px; + + } + + + + >.orgimg_kr{ + width: 100%; + background-image: url(../images/organiz_kor_m.jpg); + //background-color: green; + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; + } + + >.orgimg_eng{ + width: 100%; + background-image: url(../images/organiz_m.jpg); + //background-color: green; + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; + } + + &:after { + //display: none; + position: absolute; + top : -30px; + left: 50%;//추가 + transform: translateX(-50%); + width: 90%; + height: 1px; + background-color: #ddd; + content: ''; + } + } + + >.org_eng { + //display: none; + width: 100%; + height: 400px; + //background-color: ; + + >h2 { + width: 100%; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: $point-color; + margin-bottom:0px; + } + + &:after { + position: absolute; + top : -25px; + width: 90%; + height: 1px; + background-color: #ddd; + content: ''; + } + } + }//end of organiz + + + + }//end of status + +}//status 768px 반응형 + + + +/*연혁*/ + + +#since { + width: 100%; + margin-bottom: 60px; + //background-color: green; + + + //height: 750px; + background-color: #fff; + + + >.since { + position: relative; + width: 1000px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ + }//end of ceo_info_main + + >em { + color: $point-color2; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + + >.since_info { + width: 100%; + //background-color: orange; + + >h2 { + padding-left: 100px; + font-size: 50px; + font-weight: 500; + font-style : italic; + letter-spacing: -4px; + color: #eee; + + } + + >div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; + + >ul { + padding-left: 150px; + width: 100%; + + >li { + float: left; + margin-left: 230px; + line-height: 2.5em; + + &:first-child { + font-size: 40px; + font-weight: 900; + color: #ddd; + }//end of all li:first-child + + >dl { + padding: 5px 10px; + width: 100%; + //background-color: red; + + + >dd { + position: relative; + font-size: 16px; + font-weight: 600; + + &:after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: -20px; + width: 10px; + height: 10px; + border-radius: 15px; + background-color: $point-color2; + content: ''; + } + }//end of all dd + }//end of all dl + + }//end of all li + }//end of all ul + }//end of all div + + >.january { + + >ul { + //background-color: pink; + }//end of ul + }//end of january + + >.february { + + >ul { + //background-color: green; + }//end of ul + }//end of february + + >.march { + + >ul { + //background-color: rgb(0, 186, 191); + }//end of ul + }//end of march + }//end of since_info + + }//end of ceo_info + +}//end of since + +@media screen and(max-width : 768px) {/*since 768px 반응형*/ + + #since { + width: 100%; + margin-bottom: 0px;//변경 + padding-bottom: 80px;//추가 + //background-color: green; + + + height: auto;//변경 + background-color: #fff; + + + >.since { + position: relative; + width: 90%; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 22px;//변경 + font-weight: 600;//변경 + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ + }//end of ceo_info_main + + >em { + color: $point-color2; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + + >.since_info { + width: 100%; + //background-color: orange; + + >h2 { + padding-bottom: 20px;//추가 + padding-left: 0px;//변경 + font-size: 50px; + font-weight: 500; + font-style : italic; + letter-spacing: -4px; + color: #eee; + + } + + >div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; + + >ul { + padding-left: 0px;//변경 + width: 100%; + + >li { + float: inherit; + margin-left: 0px;//변경 + line-height: 1.45em; + + &:first-child { + display: none; + font-size: 40px; + font-weight: 900; + color: #ddd; + }//end of all li:first-child + + >dl { + padding: 5px 0px;//변경 + width: 100%; + //background-color: red; + + + >dd { + position: relative; + font-size: 14px; + font-weight: 500; + padding-bottom: 10px;//추가 + + &:after { + position: absolute; + top: 11px; + transform: translateY(-50%); + left: -10px; + width: 5px; + height: 5px; + border-radius: 15px; + background-color: $point-color2; + content: ''; + } + }//end of all dd + }//end of all dl + + }//end of all li + }//end of all ul + }//end of all div + + >.january { + + >ul { + //background-color: pink; + }//end of ul + }//end of january + + >.february { + + >ul { + //background-color: green; + }//end of ul + }//end of february + + >.march { + + >ul { + //background-color: rgb(0, 186, 191); + }//end of ul + }//end of march + }//end of since_info + + }//end of ceo_info + + }//end of since + + + +}//since 768px 반응형 + + +/*보유인증현황*/ + + +#certificate { + width: 100%; + margin-bottom: 0 auto; + //background-color: green; + height: 1700px; + background-color: #fff; + + + >.certificate { + position: relative; + width: 1000px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #ddd; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >.certificate_info { + width: 100%; + //background-color: green; + + >div { + width: 100%; + + >ul { + + >li { + float: left; + margin: 0 47px 50px 0; + width: 300px; + height: 400px; + //background-color: pink; + border: 1px dotted #eee; + + &:last-child { + margin-right: 0; + } + + >dl { + + >dt { + width: 300px; + height: 350px; + text-indent: -99999px; + //background-color: orange; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + } + >dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; + } + }//end of all dl + }//end of all li + }//end of all ul + }//end of all div + + + >.sect01 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); + } + + }//end of sect01 img + + >.sect02 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); + } + + }//end of sect02 img + + + >.sect03 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); + } + &:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; + } + &:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_10.png); + background-position: 50% 50%; + } + + + + }//end of sect03 img + + }//end of certificate_info--> + + }//end of ceo_info + +}//end of certificate + + +@media screen and(max-width : 768px) {/*certificate 768px 반응형*/ + + + #certificate { + width: 100%;//변경 + //padding-bottom: 60px; + margin-bottom: 0 auto 0;//변경 + //background-color: green; + height: auto;//변경 + background-color: #fff; + + >.index_tap { + >p { + >span { + + >a { + padding-right: 240px; + } + } + } + } + + + >.certificate { + position: relative; + width: 100%; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + width: 100%;//추가 + text-align: center; + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 22px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #ddd; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >.certificate_info { + width: 100%; + //background-color: green; + + >div { + width: 100%; + + >ul { + width: 100%;//추가 + + >li { + float: inherit; + margin: 0 0px 50px 0; + width: 100%; + height: 400px; + //background-color: pink; + border: 1px dotted #eee; + border-top: none;//추가 + border-left: none;//추가 + border-right: none;//추가 + + &:last-child { + margin-right: 0; + } + + >dl { + + >dt { + width: 100%; + height: 350px; + text-indent: -99999px; + //background-color: orange; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; + } + >dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; + } + }//end of all dl + }//end of all li + }//end of all ul + }//end of all div + + + >.sect01 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); + } + + }//end of sect01 img + + >.sect02 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); + } + + }//end of sect02 img + + + >.sect03 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); + } + &:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; + } + &:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_10.png); + background-position: 50% 50%; + } + + + }//end of sect03 img + + }//end of certificate_info--> + + }//end of ceo_info + + }//end of certificate + + +}//certificate 768px 반응형 + + +/* +#research { + width: 100%; + height: 3500px; + margin-bottom: 0 auto; + //background-color: green; + background-color: #fff; + background-image: url(../images/bus_bg.jpg); + background-repeat: repeat-Y; + + .research { + width: 100%; + height: 400px; + margin-bottom: 40px; + background-color: #fff; + + + >.inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + }//end of class research + + .inner { + + + >.rndSys { + width: 100%; + //background-color: green; + + >.camera { + margin: 0 auto; + width: 900px; + height: 600px; + background-image: url(../images/camera.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + }//end of camera + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + + } + + } + }//ednd of ul + + .rndSys_info { + padding-top: 10px; + line-height: 1.5em; + color: #aaa; + cursor: default; + }//end of rndSys_info + }//end of rndSys + + + + .strength { + margin-top: 150px; + width: 100%; + + >.strength_box1 { + float: left; + width: 870px; + height: 560px; + //background-color: orange; + + >ul { + padding: 50px 0 0 30px; + //background-color: orange; + + >li { + float: left; + + + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >.strength_top { + margin-top: 50px; + padding-left: 30px; + width: 870px; + height: 200px; + //background-color: green; + + >ul { + >li { + float: left; + width: 415px; + height: 200px; + + &:first-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_01.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_터널 유고영상 빅데이터 확보 + + &:last-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_02.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_현존하는 시스템의 한계극복기능 + + >dl { + width: 100%; + + >dt { + width: 415px; + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {//아이콘의 공통 스타일 + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + }//end of first-child + + &:last-child {//아이콘 옆 글자 + + >dl { + padding-left: 15px; + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 10px 0; + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_top + + >.strength_bot { + padding-left: 30px; + width: 870px; + height: 200px; + //background-color: green; + + >ul { + >li { + float: left; + width: 415px; + height: 200px; + + &:first-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_03.png); + }//우수한 경제성 아이콘 + + }//end of ul li:first-child_우수한 경제성 아이콘 + + &:last-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_04.png); + }//지속적인 기술력 성장 아이콘 + + }//end of ul li:first-child_속적인 기술력 성장 아이콘 + + >dl { + width: 100%; + + >dt { + width: 415px; + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {//아이콘의 공통 스타일 + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + }//end of first-child + + &:last-child {//아이콘 옆 글자 + + >dl { + padding-left: 15px; + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 10px 0; + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_bot + + }//end of strength_box1 + + >.strength_box2 { + float: left; + width: 330px; + height: 560px; + background-image: url(../images/strength.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 0; + + }//end of strength_box2 + + + }//end of strength + + + >.rnd_schedule { + width: 100%; + margin-top: 150px; + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//end of ul + + >.schedule_content { + margin-top: 30px; + + >ul { + width: 1000px; + height: 70px; + margin-bottom: 10px; + //background-color: orange; + + >li { + float: left; + + &:first-child { + width: 270px; + height: 100%; + background-color: #1e3571; + text-align: center; + font-size: 16px; + font-weight: 600; + line-height: 70px; + color: #fff; + cursor: default; + }//end of 스케쥴 제목 + + &:last-child { + width: 730px; + height: 100%; + border: 1px solid #1e3571; + box-sizing: border-box; + padding: 30px; + font-size: 16px; + font-weight: 600; + line-height: 10px; + cursor: default; + transition-duration: .2s; + + >em { + opacity: 0; + } + }//end of 스케쥴 제목 + + }//end of li + }//end of ul + }//end of schedule_content + + + + + }//end of rnd_schedule + + + >.rnd_outside { + width: 100%; + margin-top: 150px; + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >ol { + margin-top: 30px; + width: 100%; + + >li { + float: left; + width: 300px; + height: 570px; + background-repeat: no-repeat; + background-size: cover; + + &:nth-child(1) { + background-image: url(../images/thief.png); + background-position:24% 50%; + } + &:nth-child(2) { + background-image: url(../images/lamp.jpg); + background-position:60% 50%; + } + &:nth-child(3) { + background-image: url(../images/auto_btn.png); + background-position:50% 50%; + } + &:nth-child(4) { + background-image: url(../images/hemet.jpg); + background-position:45% 50%; + } + + >dl { + opacity: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.6); + color: #fff; + text-align: center; + cursor: default; + + >dt { + position: relative; + padding-top: 150px; + font-size: 25px; + + &:after { + position: absolute; + top: 190px; + left: 50%; + transform: translateX(-50%); + width: 20px; + height: 1px; + background-color: #fff; + content: ''; + } + } + + >dd { + padding: 30px 30px 0 30px; + font-size: 14px; + text-align: center; + line-height: 1.6em; + } + } + }//end of li + } + + }//end of rnd_outside + }//end of inner + +}//end of #research + +//연구개발 모바일버전 + +@media screen and(max-width : 768px) { + #research { + width: 100%; + height: auto;//m + margin-bottom: 0 auto; + //background-color: green; + background-color: #fff; + background-image: url(../images/bus_bg.jpg); + background-repeat: repeat-Y; + + .research { + width: 100%; + height: 400px; + margin-bottom: 40px; + background-color: #fff; + + + >.inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + }//end of class research + + .inner { + + + >.rndSys { + width: 100%; + //background-color: green; + + >.camera { + margin: 0 auto; + width: 100%;//m + height: 300px;//m + background-image: url(../images/camera.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain;//m + }//end of camera + + >ul { + //background-color: orange; + + >li { + float: inherit;//m + + &:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px;//m + + } + &:last-child { + display: none;//m + font-size: 16px; + padding-top: 5px;//m + padding-left: 10px;//m + padding-right: 10px;//m + + } + + } + }//ednd of ul + + .rndSys_info { + padding-top: 10px; + padding: 10px;//m + line-height: 1.5em; + color: #aaa; + cursor: default; + }//end of rndSys_info + }//end of rndSys + + + + .strength { + margin-top: 50px;//m + width: 100%; + + >.strength_box1 { + float: inherit;//m + width: 100%;//m + height: 560px; + //background-color: orange; + + >ul { + padding: 0px 0 0 0px;//m + //background-color: orange; + + >li { + float: inherit;//m + + &:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px;//m + } + &:last-child { + display: none;//m + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >.strength_top { + margin-top: 30px;//m + padding-left: 0px;//m + padding-right: 0px;//m + width: 100%;//m + height: 170px;//m + + //background-color: green; + + >ul { + >li { + float: left; + width: 100%; + height: 170px; + border-bottom: 1px dashed #ccc; + + &:first-child { + height: 160px;//m + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_01.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_터널 유고영상 빅데이터 확보 + + &:last-child { + padding-top: 50px;//m + height: 200px;//m + + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_02.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_현존하는 시스템의 한계극복기능 + + >dl { + width: 100%; + + >dt { + width: 100%;//m + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {//아이콘의 공통 스타일 + width: 40px; + height: 40px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + margin-left: 10px;//m + }//end of first-child + + &:last-child {//아이콘 옆 글자 + + >dl { + padding-left: 10px;//m + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 0px 0;//m + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 0px 0 0 10px;//m + font-size: 15px; + line-height: 1.45em; + color: #333; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_top + + >.strength_bot { + padding-left: 0px;//m + padding-right: 0px;//m + width: 100%;//m + height: 200px; + //background-color: green; + + + >ul { + >li { + float: left; + width: 100%; + height: 200px; + border-bottom: 1px dashed #ccc; + + &:first-child { + padding-top: 50px;//m + height: 160px;//m + + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_03.png); + }//우수한 경제성 아이콘 + + }//end of ul li:first-child_우수한 경제성 아이콘 + + &:last-child { + padding-top: 50px;//m + height: 160px;//m + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_04.png); + }//지속적인 기술력 성장 아이콘 + + }//end of ul li:first-child_속적인 기술력 성장 아이콘 + + >dl { + width: 100%; + + >dt { + width: 100%;//m + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {//아이콘의 공통 스타일 + width: 40px; + height: 40px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + margin-left: 10px;//m + }//end of first-child + + &:last-child {//아이콘 옆 글자 + + >dl { + padding-left: 10px;//m + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 0px 0;//m + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 0px 0 0 10px;//m + font-size: 15px; + line-height: 1.45em; + color: #333; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_bot + + }//end of strength_box1 + + >.strength_box2 { + display: none;//m + float: left; + width: 330px; + height: 560px; + background-image: url(../images/strength.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 0; + + }//end of strength_box2 + + + }//end of strength + + + >.rnd_schedule { + width: 100%; + margin-top: 80px;//m + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px;//m + } + &:last-child { + display: none;//m + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//end of ul + + >.schedule_content { + width: 100%;//m + margin-top: 30px; + + >ul { + width: 90%; + height: auto;//m + //margin-bottom: 10px; + margin: 0 auto 10px;//m + //background-color: orange; + + >li { + float: inherit;//m + + &:first-child { + width: 100%; + height: 100%; + background-color: #1e3571; + text-align: center; + font-size: 16px; + font-weight: 600; + line-height: 70px; + color: #fff; + cursor: default; + }//end of 스케쥴 제목 + + &:last-child { + width: 100%; + height: 100%; + border: 1px solid #1e3571; + box-sizing: border-box; + padding: 30px; + font-size: 16px; + font-weight: 600; + line-height: 1.45em;//m + cursor: default; + transition-duration: .2s; + + >em { + opacity: 0; + } + }//end of 스케쥴 제목 + + }//end of li + }//end of ul + }//end of schedule_content + + + + + }//end of rnd_schedule + + + >.rnd_outside { + width: 100%; + margin-top: 80px;//m + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px;//m + } + &:last-child { + display: none;//m + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >ol { + margin-top: 30px; + width: 100%; + + >li { + float: left; + width: 100%;//m + height: 200px;//m + background-repeat: no-repeat; + background-size: cover; + + &:nth-child(1) { + background-image: url(../images/thief.png); + background-position:24% 50%; + } + &:nth-child(2) { + background-image: url(../images/lamp.jpg); + background-position:60% 50%; + } + &:nth-child(3) { + background-image: url(../images/auto_btn.png); + background-position:50% 50%; + } + &:nth-child(4) { + background-image: url(../images/hemet.jpg); + background-position:45% 50%; + } + + >dl { + opacity: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.6); + color: #fff; + text-align: center; + cursor: default; + + >dt { + position: relative; + padding-top: 50px;//m + font-size: 25px; + + &:after { + position: absolute; + top: 90px; + left: 50%; + transform: translateX(-50%); + width: 20px; + height: 1px; + background-color: #fff; + content: ''; + } + } + + >dd { + padding: 30px 30px 0 30px; + font-size: 14px; + text-align: center; + line-height: 1.6em; + text-align: center;//m + } + } + }//end of li + } + + }//end of rnd_outside + }//end of inner + + }//end of #research + +}//end of research 모바일 +*/ + + + +#research { + width: 100%; + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + width: 100%; + height: 180px; + padding-top: 60px; + margin: 0 auto; + background-image: url(../images/research_m01.jpg); + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + color: #fff; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + + >.threeTap { + width: 100%; + //height: 40px; + //background-color: green; + ul { + width: 960px; + margin: 0 auto; + //background-color: pink; + >li { + display: block; + float: left; + margin: 0 20px; + font-size: 20px; + font-weight: 600; + color: #fff; + cursor: default; + + } + } + }//end of threetap + }//end of inner + + + >.research { + padding-top: 130px; + margin-bottom : 100px; + width: 100%; + //background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + //margin-top: 60px; + + >ul { + //background-color: green; + >li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + text-indent: -99999px; + + + } + + &:last-child { + + height: 240px; + margin-top: 120px; + //background-color: red; + + + >dl{ + padding-left: 100px; + >dt { + position: relative; + font-size: 40px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.research_01 { + >ul >li { + + &:first-child { + background-image: url(../images/camera.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of research_01 + + &.research_02 { + width: 100%; + height: 100%; + background-image: url(../images/bg_2.png); + >ul >li { + >dl{ + dt{ + color: #fff; + } + dd { + color: #fff; + } + } + + &:first-child { + background-image: url(../images/crack.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of research_02 + + &.research_03 { + >ul >li { + + &:first-child { + background-image: url(../images/moon.png); + background-size: contain; + background-repeat: no-repeat; + //background-color: orange; + } + }//end of 01 li + }//end of research_03 + + }//end of all div + + }//end of class business +}//end of #research + +@media screen and(max-width : 768px) {//business 768px 반응형 + + #research { + width: 100%; + + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + height: 180px; + padding-top: 30px; + margin: 0 auto; + background-image: url(../images/research_m01.jpg); + + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 22px;//변경 + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 50px;//변경 + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + >.threeTap { + width: 100%; + height: 100%; + //background-color: green; + ul { + width: 100%; + margin: 0 auto; + //background-color: pink; + >li { + display: block; + float: inherit;//변경 + text-align: center;//추가 + margin: 10px 20px;//변경 + font-size: 20px; + font-weight: 600; + color: #fff; + cursor: default; + + } + } + }//end of threetap + }//end of inner + + >.category { + position: fixed;//추가 + bottom: 0;//추가 + width: 100%; + border-bottom: 1px solid #ddd;//변경 + z-index: 99999; + //ackground-color: green; + + >ul { + margin: 0 auto; + width: 100%;//변경 + + + >li { + float: left;//변경 + width: 25%;//변경 + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px;//변경 + background-color: #eee; + //border-bottom: 1px solid #555; + + color: #555; + cursor: pointer; + + &:last-child { + margin-right: 0; + border-bottom: none; + } + + &:hover { + color:#fff; + background-color: $point-color; + } + + &.on { + color:#fff; + background-color: $point-color; + } + + + }//end of li + }//end of ul + }//end of category + + >.research { + padding-top: 0px;//변경 + width: 100%; + background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + margin-top: 30px;//추가 + + &:first-child { + margin-top: 0; + } + + + >ul { + //background-color: green; + >li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + height: 200px; + float: inherit!important;//추가 + text-indent: -99999px; + + + } + + &:last-child { + height: auto; + margin-top: 20px;//변경 + //background-color: red; + + + >dl{ + width: 90%;//추기 + padding-left: 0px; + margin: 0 auto;//추가 + >dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + display: none; + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + >br { + display: none; + } + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.research_01 { + >ul >li { + + &:first-child { + background-image: url(../images/camera.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of research_01 + + &.research_02 { + width: 100%; + height: 100%; + background-image: url(../images/bg_2.png); + >ul >li { + >dl{ + dt{ + color: #fff; + } + dd { + color: #fff; + } + } + + &:first-child { + background-image: url(../images/crack.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of research_02 + + &.research_03 { + >ul >li { + + &:first-child { + background-image: url(../images/moon.png); + background-size: contain; + background-repeat: no-repeat; + //background-color: orange; + } + }//end of 01 li + }//end of research_03 + + }//end of all div + + }//end of class business + }//end of #business + +}//business 768px 반응형 + + + + + + + + + + + +/*사업영역*/ + +#business { + width: 100%; + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + >.category { + width: 100%; + border-bottom: 1px solid #eee; + //ackground-color: green; + + >ul { + margin: 0 auto; + width: 850px; + + + >li { + float: left; + width: 24%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 3px; + background-color: #ddd; + color: #555; + cursor: pointer; + + &:last-child { + margin-right: 0; + } + + &:hover { + color:#fff; + background-color: $point-color; + } + + &.on { + color:#fff; + background-color: $point-color; + } + + + }//end of li + }//end of ul + }//end of category + + >.business { + padding-top: 130px; + width: 100%; + background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + //margin-top: 60px; + + >ul { + //background-color: green; + >li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + text-indent: -99999px; + + + } + + &:last-child { + + height: 240px; + margin-top: 120px; + //background-color: red; + + + >dl{ + padding-left: 100px; + >dt { + position: relative; + font-size: 40px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.business_01 { + >ul >li { + + &:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_02 { + >ul >li { + + &:first-child { + background-image: url(../images/bigdata.jpg); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_03 { + >ul >li { + + &:first-child { + background-image: url(../images/soc.jpg); + background-size: contain; + background-repeat: no-repeat; + //background-color: orange; + } + }//end of 01 li + }//end of business_01 + + &.business_04 { + padding-bottom: 100px; + >ul >li { + + &:first-child { + background-image: url(../images/si.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 0 88%; + //background-color: pink; + } + }//end of 01 li + }//end of business_01 + }//end of all div + + }//end of class business +}//end of #business + +@media screen and(max-width : 768px) {//business 768px 반응형 + + #business { + width: 100%; + + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + height: 50px; + padding-top: 60px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 22px;//변경 + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 50px;//변경 + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 15px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + >.category { + position: fixed;//추가 + bottom: 0;//추가 + width: 100%; + border-bottom: 1px solid #ddd;//변경 + z-index: 99999; + //ackground-color: green; + + >ul { + margin: 0 auto; + width: 100%;//변경 + + + >li { + float: left;//변경 + width: 25%;//변경 + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px;//변경 + background-color: #eee; + //border-bottom: 1px solid #555; + + color: #555; + cursor: pointer; + + &:last-child { + margin-right: 0; + border-bottom: none; + } + + &:hover { + color:#fff; + background-color: $point-color; + } + + &.on { + color:#fff; + background-color: $point-color; + } + + + }//end of li + }//end of ul + }//end of category + + >.business { + padding-top: 0px;//변경 + width: 100%; + background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + margin-top: 30px;//추가 + + &:first-child { + margin-top: 0; + } + + + >ul { + //background-color: green; + >li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + height: 200px; + float: inherit!important;//추가 + text-indent: -99999px; + + + } + + &:last-child { + height: auto; + margin-top: 20px;//변경 + //background-color: red; + + + >dl{ + width: 90%;//추기 + padding-left: 0px; + margin: 0 auto;//추가 + >dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + >br { + display: none; + } + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.business_01 { + >ul >li { + + &:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_02 { + + >ul >li { + + &:first-child { + + background-image: url(../images/bigdata.jpg); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_03 { + >ul >li { + + &:first-child { + background-image: url(../images/soc.jpg); + background-size: cover; + background-repeat: no-repeat; + //background-color: orange; + } + }//end of 01 li + }//end of business_01 + + &.business_04 { + + padding-bottom: 40px;//변경 + >ul >li { + + &:first-child { + background-image: url(../images/si.jpg); + background-size: cover;//변경 + background-repeat: no-repeat; + background-position: 50% 90%; + //background-color: pink; + } + }//end of 01 li + }//end of business_01 + }//end of all div + + }//end of class business + }//end of #business + +}//business 768px 반응형 + + + +#faq { + position: relative; + width: 100%; + margin-bottom: 60px; + //background-color: green; + height: 550px; + background-color: #fff; + + + >.inner { + width: 1000px; + margin: 0 auto; + + >.faq_info { + float: left; + width: 450px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + + &:last-child { + margin-top: 50px; + font-size: 17px; + color: $point-color; + font-weight: 600; + } + + >span { + font-size: 20px; + font-weight: 600; + } + + >em { + color: #eee; + } + + &.faq_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + } + }//end of ul + }//end of ceo_info + >.map { + float: right; + margin-top: 50px; + width : 540px; + height : 400px; + border : 0; + + } + + }//end of inner + + +}//end of faq + +@media screen and(max-width : 768px) {//faq768px 반응형 + + #faq { + position: relative; + width: 100%; + padding-bottom: 60px; + margin-bottom: 0px;//변경 + //background-color: green; + height: auto; + background-color: #fff; + + + >.inner { + width: 100%;//변경 + margin: 0 auto; + + >.faq_info { + float: inherit;//변경 + width: 90%; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + + &:last-child { + border-top: 1px dotted #ddd;//추가 + margin-top: 20px;//변경 + padding-top: 10px;//추가 + font-size: 14px; + color: $point-color; + font-weight: 600; + } + + >span { + font-size: 17px; + font-weight: 600; + } + + >em { + color: #eee; + } + + &.faq_info_main { + position: relative; + text-align: center;//추가 + font-size: 22px;//변경 + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + } + }//end of ul + }//end of ceo_info + >.map { + float: inherit; + margin-top: 20px; + width : 100%; + height : 400px; + border : 0; + + }// end of mobile map + + }//end of inner + + + }//end of faq + +}//faq 768px 반응형 + + + +/*반응형*/ +.pos_right { + background-color: red; + //text-align: right; + + >dl { + + + >dt { + &:after { + left: 200px; + } + } + } + + + +}//end of pos_right diff --git a/eng/css/style_eng.css b/eng/css/style_eng.css new file mode 100644 index 0000000..e05ccdd --- /dev/null +++ b/eng/css/style_eng.css @@ -0,0 +1,1621 @@ +@charset "UTF-8"; +/*일반현황*/ +.index_tap { + width: 100%; + height: 35px; + border-bottom: 1px solid #eee; + background-color: #ffffff; } + .index_tap > p { + margin: 0 auto; + width: 1000px; + font-size: 13px; + line-height: 35px; + text-align: right; + color: #333; } + .index_tap > p > em { + padding: 0 3px; + font-weight: 900; + color: #ffc700; } + .index_tap > p > span > a { + color: #222; + font-weight: 900; } + .index_tap > p > span > a:hover { + text-decoration: underline; } + +@media screen and (max-width: 768px) { + /*index_tap 768px 반응형*/ + .index_tap { + width: 100%; + height: 35px; + border-bottom: 1px solid #eee; + background-color: #ffffff; } + .index_tap > p { + margin: 0 auto; + width: 100%; + font-size: 13px; + line-height: 35px; + text-align: center; + color: #333; } + .index_tap > p > em { + padding: 0 3px; + font-weight: 900; + color: #ffc700; } + .index_tap > p > span > a { + padding-right: 240px; + color: #222; + font-weight: 900; } + .index_tap > p > span > a:hover { + text-decoration: underline; } } +.index_tap2 { + background-color: transparent; + border-bottom: 1px solid #e1e1e1; } + +#status { + width: 100%; + margin-bottom: 60px; + height: 1350px; + background-color: #fff; } + #status > .status { + position: relative; + width: 1000px; + margin: 0 auto 100px; } + #status > .status > ul { + margin-top: 60px; + width: 100%; } + #status > .status > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #status > .status > ul > li.status_info_main { + position: relative; + font-size: 20px; + font-weight: 700; + color: #1e3571; + margin-bottom: 70px; + line-height: 1.3em; } + #status > .status > ul > li.status_info_main:after { + position: absolute; + top: 85px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #status > .status > ul > li > em { + color: #eee; } + #status > .status > ul > li > span { + font-size: 20px; } + #status > .status > ol { + margin-top: 50px; + color: #bbb; + line-height: 1.4em; } + #status > .status > ol > li { + font-size: 13px; } + #status > .status > ol > li:first-child { + font-size: 18px; + margin-bottom: 10px; } + #status > .status:after { + position: absolute; + top: 120px; + right: 0; + width: 260px; + height: 345px; + background-image: url(../images/company_3.png); + background-repeat: no-repeat; + background-position: 0 100%; + background-size: contain; + content: ''; } + #status > .organiz { + width: 100%; + height: 700px; } + #status > .organiz > .inner { + position: relative; + width: 1000px; + height: 600px; } + #status > .organiz > .inner > h2 { + width: 1000px; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: #1e3571; + margin-bottom: 0px; } + #status > .organiz > .inner > .orgimg { + width: 100%; + height: 100%; + background-image: url(../images/organiz.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; } + #status > .organiz > .inner:after { + position: absolute; + top: 65px; + width: 1000px; + height: 1px; + background-color: #ddd; + content: ''; } + #status > .organiz > .org_eng { + position: relative; + width: 1000px; + height: 600px; + background-image: url(../images/organiz_eng.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; } + #status > .organiz > .org_eng > h2 { + width: 1000px; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: #1e3571; + margin-bottom: 0px; } + #status > .organiz > .org_eng:after { + position: absolute; + top: 65px; + width: 1000px; + height: 1px; + background-color: #ddd; + content: ''; } + +@media screen and (max-width: 768px) { + #status { + width: 100%; + margin-bottom: 0px; + padding-bottom: 60px; + height: auto; + background-color: #fff; } + #status > .status { + position: relative; + width: 90%; + padding-bottom: 50px; + margin: 0 auto 0px; } + #status > .status > ul { + margin-top: 60px; + width: 100%; } + #status > .status > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #status > .status > ul > li.status_info_main { + position: relative; + font-size: 20px; + font-weight: 700; + color: #1e3571; + margin-bottom: 70px; + line-height: 1.3em; } + #status > .status > ul > li.status_info_main > br { + display: none; } + #status > .status > ul > li.status_info_main:after { + position: absolute; + top: 85px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #status > .status > ul > li > em { + color: #eee; } + #status > .status > ul > li > span { + font-size: 20px; } + #status > .status > ol { + margin-top: 50px; + color: #bbb; + line-height: 1.4em; } + #status > .status > ol > li { + font-size: 13px; } + #status > .status > ol > li:first-child { + font-size: 18px; + margin-bottom: 10px; } + #status > .status:after { + display: none; + position: absolute; + top: 120px; + right: 0; + width: 260px; + height: 345px; + background-image: url(../images/company_3.png); + background-repeat: no-repeat; + background-position: 0 100%; + background-size: contain; + content: ''; } + #status > .organiz { + width: 100%; + height: 400px; } + #status > .organiz > .inner { + position: relative; + width: 350px; + height: 350px; + background-image: none; } + #status > .organiz > .inner > h2 { + width: 100%; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: #1e3571; + margin-bottom: 0px; } + #status > .organiz > .inner > .orgimg_kr { + width: 100%; + background-image: url(../images/organiz_kor_m.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; } + #status > .organiz > .inner > .orgimg_eng { + width: 100%; + background-image: url(../images/organiz_m.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; } + #status > .organiz > .inner:after { + position: absolute; + top: -30px; + left: 50%; + transform: translateX(-50%); + width: 90%; + height: 1px; + background-color: #ddd; + content: ''; } + #status > .organiz > .org_eng { + width: 100%; + height: 400px; } + #status > .organiz > .org_eng > h2 { + width: 100%; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: #1e3571; + margin-bottom: 0px; } + #status > .organiz > .org_eng:after { + position: absolute; + top: -25px; + width: 90%; + height: 1px; + background-color: #ddd; + content: ''; } } +/*연혁*/ +#since { + width: 100%; + margin-bottom: 60px; + height: 750px; + background-color: #fff; } + #since > .since { + position: relative; + width: 1000px; + margin: 0 auto; } + #since > .since > ul { + margin-top: 80px; + width: 100%; } + #since > .since > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #since > .since > ul > li.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ } + #since > .since > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #since > .since > ul > li > em { + color: #ffc700; } + #since > .since > ul > li > span { + font-size: 20px; } + #since > .since > .since_info { + width: 100%; } + #since > .since > .since_info > h2 { + padding-left: 100px; + font-size: 50px; + font-weight: 500; + font-style: italic; + letter-spacing: -4px; + color: #eee; } + #since > .since > .since_info > div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; } + #since > .since > .since_info > div > ul { + padding-left: 150px; + width: 100%; } + #since > .since > .since_info > div > ul > li { + float: left; + margin-left: 230px; + line-height: 2.5em; } + #since > .since > .since_info > div > ul > li:first-child { + font-size: 40px; + font-weight: 900; + color: #ddd; } + #since > .since > .since_info > div > ul > li > dl { + padding: 5px 10px; + width: 100%; } + #since > .since > .since_info > div > ul > li > dl > dd { + position: relative; + font-size: 16px; + font-weight: 600; } + #since > .since > .since_info > div > ul > li > dl > dd:after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: -20px; + width: 10px; + height: 10px; + border-radius: 15px; + background-color: #ffc700; + content: ''; } + +@media screen and (max-width: 768px) { + /*since 768px 반응형*/ + #since { + width: 100%; + margin-bottom: 0px; + padding-bottom: 80px; + height: auto; + background-color: #fff; } + #since > .since { + position: relative; + width: 90%; + margin: 0 auto; } + #since > .since > ul { + margin-top: 80px; + width: 100%; } + #since > .since > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #since > .since > ul > li.status_info_main { + position: relative; + font-size: 22px; + font-weight: 600; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ } + #since > .since > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #since > .since > ul > li > em { + color: #ffc700; } + #since > .since > ul > li > span { + font-size: 20px; } + #since > .since > .since_info { + width: 100%; } + #since > .since > .since_info > h2 { + padding-bottom: 20px; + padding-left: 0px; + font-size: 50px; + font-weight: 500; + font-style: italic; + letter-spacing: -4px; + color: #eee; } + #since > .since > .since_info > div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; } + #since > .since > .since_info > div > ul { + padding-left: 0px; + width: 100%; } + #since > .since > .since_info > div > ul > li { + float: inherit; + margin-left: 0px; + line-height: 1.45em; } + #since > .since > .since_info > div > ul > li:first-child { + display: none; + font-size: 40px; + font-weight: 900; + color: #ddd; } + #since > .since > .since_info > div > ul > li > dl { + padding: 5px 0px; + width: 100%; } + #since > .since > .since_info > div > ul > li > dl > dd { + position: relative; + font-size: 14px; + font-weight: 500; + padding-bottom: 10px; } + #since > .since > .since_info > div > ul > li > dl > dd:after { + position: absolute; + top: 11px; + transform: translateY(-50%); + left: -10px; + width: 5px; + height: 5px; + border-radius: 15px; + background-color: #ffc700; + content: ''; } } +/*보유인증현황*/ +#certificate { + width: 100%; + margin-bottom: 0 auto; + height: 1700px; + background-color: #fff; } + #certificate > .certificate { + position: relative; + width: 1000px; + margin: 0 auto; } + #certificate > .certificate > ul { + margin-top: 80px; + width: 100%; } + #certificate > .certificate > ul > li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #certificate > .certificate > ul > li.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #certificate > .certificate > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #certificate > .certificate > ul > li > em { + color: #ddd; } + #certificate > .certificate > ul > li > span { + font-size: 20px; } + #certificate > .certificate > .certificate_info { + width: 100%; } + #certificate > .certificate > .certificate_info > div { + width: 100%; } + #certificate > .certificate > .certificate_info > div > ul > li { + float: left; + margin: 0 47px 50px 0; + width: 300px; + height: 400px; + border: 1px dotted #eee; } + #certificate > .certificate > .certificate_info > div > ul > li:last-child { + margin-right: 0; } + #certificate > .certificate > .certificate_info > div > ul > li > dl > dt { + width: 300px; + height: 350px; + text-indent: -99999px; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; } + #certificate > .certificate > .certificate_info > div > ul > li > dl > dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; } + +@media screen and (max-width: 768px) { + /*certificate 768px 반응형*/ + #certificate { + width: 100%; + margin-bottom: 0 auto 0; + height: auto; + background-color: #fff; } + #certificate > .index_tap > p > span > a { + padding-right: 240px; } + #certificate > .certificate { + position: relative; + width: 100%; + margin: 0 auto; } + #certificate > .certificate > ul { + margin-top: 80px; + width: 100%; } + #certificate > .certificate > ul > li { + width: 100%; + text-align: center; + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; } + #certificate > .certificate > ul > li.status_info_main { + position: relative; + font-size: 22px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #certificate > .certificate > ul > li.status_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #certificate > .certificate > ul > li > em { + color: #ddd; } + #certificate > .certificate > ul > li > span { + font-size: 20px; } + #certificate > .certificate > .certificate_info { + width: 100%; } + #certificate > .certificate > .certificate_info > div { + width: 100%; } + #certificate > .certificate > .certificate_info > div > ul { + width: 100%; } + #certificate > .certificate > .certificate_info > div > ul > li { + float: inherit; + margin: 0 0px 50px 0; + width: 100%; + height: 400px; + border: 1px dotted #eee; + border-top: none; + border-left: none; + border-right: none; } + #certificate > .certificate > .certificate_info > div > ul > li:last-child { + margin-right: 0; } + #certificate > .certificate > .certificate_info > div > ul > li > dl > dt { + width: 100%; + height: 350px; + text-indent: -99999px; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; } + #certificate > .certificate > .certificate_info > div > ul > li > dl > dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); } + #certificate > .certificate > .certificate_info > .sect01 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); } + #certificate > .certificate > .certificate_info > .sect02 > ul > li:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); } + #certificate > .certificate > .certificate_info > .sect03 > ul > li:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_08.png); + background-position: 50% 50%; } } +#research { + width: 100%; + height: 3500px; + margin-bottom: 0 auto; + background-color: #fff; + background-image: url(../images/bus_bg.jpg); + background-repeat: repeat-Y; } + #research .research { + width: 100%; + height: 400px; + margin-bottom: 40px; + background-color: #fff; } + #research .research > .inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; } + #research .research > .inner > h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; } + #research .research > .inner > h2:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #research .research > .inner p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; } + #research .inner > .rndSys { + width: 100%; } + #research .inner > .rndSys > .camera { + margin: 0 auto; + width: 900px; + height: 600px; + background-image: url(../images/camera.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; } + #research .inner > .rndSys > ul > li { + float: left; } + #research .inner > .rndSys > ul > li:first-child { + font-size: 32px; + font-weight: 600; } + #research .inner > .rndSys > ul > li:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; } + #research .inner > .rndSys .rndSys_info { + padding-top: 10px; + line-height: 1.5em; + color: #aaa; + cursor: default; } + #research .inner .strength { + margin-top: 150px; + width: 100%; } + #research .inner .strength > .strength_box1 { + float: left; + width: 870px; + height: 560px; } + #research .inner .strength > .strength_box1 > ul { + padding: 50px 0 0 30px; } + #research .inner .strength > .strength_box1 > ul > li { + float: left; } + #research .inner .strength > .strength_box1 > ul > li:first-child { + font-size: 32px; + font-weight: 600; } + #research .inner .strength > .strength_box1 > ul > li:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; } + #research .inner .strength > .strength_box1 > .strength_top { + margin-top: 50px; + padding-left: 30px; + width: 870px; + height: 200px; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li { + float: left; + width: 415px; + height: 200px; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li:first-child > dl > dt > ol > li:first-child { + background-image: url(../images/strength_01.png); } + #research .inner .strength > .strength_box1 > .strength_top > ul > li:last-child > dl > dt > ol > li:first-child { + background-image: url(../images/strength_02.png); } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl { + width: 100%; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt { + width: 415px; + height: 60px; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li { + float: left; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:first-child { + /*아이콘의 공통 스타일*/ + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child { + /*아이콘 옆 글자*/ } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child > dl { + padding-left: 15px; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child > dl > dt { + font-size: 17px; + font-weight: 600; + padding: 5px 0 10px 0; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child > dl > dd { + font-size: 13px; + font-weight: 500; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child > dl > .line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dd { + padding: 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_bot { + padding-left: 30px; + width: 870px; + height: 200px; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li { + float: left; + width: 415px; + height: 200px; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li:first-child > dl > dt > ol > li:first-child { + background-image: url(../images/strength_03.png); } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li:last-child > dl > dt > ol > li:first-child { + background-image: url(../images/strength_04.png); } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl { + width: 100%; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt { + width: 415px; + height: 60px; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li { + float: left; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:first-child { + /*아이콘의 공통 스타일*/ + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child { + /*아이콘 옆 글자*/ } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child > dl { + padding-left: 15px; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child > dl > dt { + font-size: 17px; + font-weight: 600; + padding: 5px 0 10px 0; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child > dl > dd { + font-size: 13px; + font-weight: 500; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child > dl > .line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dd { + padding: 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; } + #research .inner .strength > .strength_box2 { + float: left; + width: 330px; + height: 560px; + background-image: url(../images/strength.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 0; } + #research .inner > .rnd_schedule { + width: 100%; + margin-top: 150px; } + #research .inner > .rnd_schedule > ul > li { + float: left; } + #research .inner > .rnd_schedule > ul > li:first-child { + font-size: 32px; + font-weight: 600; } + #research .inner > .rnd_schedule > ul > li:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; } + #research .inner > .rnd_schedule > .schedule_content { + margin-top: 30px; } + #research .inner > .rnd_schedule > .schedule_content > ul { + width: 1000px; + height: 70px; + margin-bottom: 10px; } + #research .inner > .rnd_schedule > .schedule_content > ul > li { + float: left; } + #research .inner > .rnd_schedule > .schedule_content > ul > li:first-child { + width: 270px; + height: 100%; + background-color: #1e3571; + text-align: center; + font-size: 16px; + font-weight: 600; + line-height: 70px; + color: #fff; + cursor: default; } + #research .inner > .rnd_schedule > .schedule_content > ul > li:last-child { + width: 730px; + height: 100%; + border: 1px solid #1e3571; + box-sizing: border-box; + padding: 30px; + font-size: 16px; + font-weight: 600; + line-height: 10px; + cursor: default; + transition-duration: .2s; } + #research .inner > .rnd_schedule > .schedule_content > ul > li:last-child > em { + opacity: 0; } + #research .inner > .rnd_outside { + width: 100%; + margin-top: 150px; } + #research .inner > .rnd_outside > ul > li { + float: left; } + #research .inner > .rnd_outside > ul > li:first-child { + font-size: 32px; + font-weight: 600; } + #research .inner > .rnd_outside > ul > li:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; } + #research .inner > .rnd_outside > ol { + margin-top: 30px; + width: 100%; } + #research .inner > .rnd_outside > ol > li { + float: left; + width: 300px; + height: 570px; + background-repeat: no-repeat; + background-size: cover; } + #research .inner > .rnd_outside > ol > li:nth-child(1) { + background-image: url(../images/thief.png); + background-position: 24% 50%; } + #research .inner > .rnd_outside > ol > li:nth-child(2) { + background-image: url(../images/lamp.jpg); + background-position: 60% 50%; } + #research .inner > .rnd_outside > ol > li:nth-child(3) { + background-image: url(../images/auto_btn.png); + background-position: 50% 50%; } + #research .inner > .rnd_outside > ol > li:nth-child(4) { + background-image: url(../images/hemet.jpg); + background-position: 45% 50%; } + #research .inner > .rnd_outside > ol > li > dl { + opacity: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.6); + color: #fff; + text-align: center; + cursor: default; } + #research .inner > .rnd_outside > ol > li > dl > dt { + position: relative; + padding-top: 150px; + font-size: 25px; } + #research .inner > .rnd_outside > ol > li > dl > dt:after { + position: absolute; + top: 190px; + left: 50%; + transform: translateX(-50%); + width: 20px; + height: 1px; + background-color: #fff; + content: ''; } + #research .inner > .rnd_outside > ol > li > dl > dd { + padding: 30px 30px 0 30px; + font-size: 14px; + text-align: left; + line-height: 1.6em; } + +/*연구개발 모바일버전*/ +@media screen and (max-width: 768px) { + #research { + width: 100%; + height: auto; + margin-bottom: 0 auto; + background-color: #fff; + background-image: url(../images/bus_bg.jpg); + background-repeat: repeat-Y; } + #research .research { + width: 100%; + height: 400px; + margin-bottom: 40px; + background-color: #fff; } + #research .research > .inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; } + #research .research > .inner > h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; } + #research .research > .inner > h2:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #research .research > .inner p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; } + #research .inner > .rndSys { + width: 100%; } + #research .inner > .rndSys > .camera { + margin: 0 auto; + width: 100%; + height: 600px; + background-image: url(../images/camera.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain; } + #research .inner > .rndSys > ul > li { + float: inherit; } + #research .inner > .rndSys > ul > li:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px; } + #research .inner > .rndSys > ul > li:last-child { + display: none; + font-size: 16px; + padding-top: 5px; + padding-left: 10px; + padding-right: 10px; } + #research .inner > .rndSys .rndSys_info { + padding-top: 10px; + padding: 10px; + line-height: 1.5em; + color: #aaa; + cursor: default; } + #research .inner .strength { + margin-top: 150px; + width: 100%; } + #research .inner .strength > .strength_box1 { + float: left; + width: 870px; + height: 560px; } + #research .inner .strength > .strength_box1 > ul { + padding: 50px 0 0 30px; } + #research .inner .strength > .strength_box1 > ul > li { + float: left; } + #research .inner .strength > .strength_box1 > ul > li:first-child { + font-size: 32px; + font-weight: 600; } + #research .inner .strength > .strength_box1 > ul > li:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; } + #research .inner .strength > .strength_box1 > .strength_top { + margin-top: 50px; + padding-left: 30px; + width: 870px; + height: 200px; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li { + float: left; + width: 415px; + height: 200px; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li:first-child > dl > dt > ol > li:first-child { + background-image: url(../images/strength_01.png); } + #research .inner .strength > .strength_box1 > .strength_top > ul > li:last-child > dl > dt > ol > li:first-child { + background-image: url(../images/strength_02.png); } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl { + width: 100%; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt { + width: 415px; + height: 60px; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li { + float: left; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:first-child { + /*아이콘의 공통 스타일*/ + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child { + /*아이콘 옆 글자*/ } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child > dl { + padding-left: 15px; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child > dl > dt { + font-size: 17px; + font-weight: 600; + padding: 5px 0 10px 0; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child > dl > dd { + font-size: 13px; + font-weight: 500; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dt > ol > li:last-child > dl > .line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; } + #research .inner .strength > .strength_box1 > .strength_top > ul > li > dl > dd { + padding: 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_bot { + padding-left: 30px; + width: 870px; + height: 200px; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li { + float: left; + width: 415px; + height: 200px; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li:first-child > dl > dt > ol > li:first-child { + background-image: url(../images/strength_03.png); } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li:last-child > dl > dt > ol > li:first-child { + background-image: url(../images/strength_04.png); } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl { + width: 100%; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt { + width: 415px; + height: 60px; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li { + float: left; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:first-child { + /*아이콘의 공통 스타일*/ + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child { + /*아이콘 옆 글자*/ } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child > dl { + padding-left: 15px; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child > dl > dt { + font-size: 17px; + font-weight: 600; + padding: 5px 0 10px 0; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child > dl > dd { + font-size: 13px; + font-weight: 500; + cursor: default; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dt > ol > li:last-child > dl > .line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; } + #research .inner .strength > .strength_box1 > .strength_bot > ul > li > dl > dd { + padding: 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; } + #research .inner .strength > .strength_box2 { + float: left; + width: 330px; + height: 560px; + background-image: url(../images/strength.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 0; } + #research .inner > .rnd_schedule { + width: 100%; + margin-top: 150px; } + #research .inner > .rnd_schedule > ul > li { + float: left; } + #research .inner > .rnd_schedule > ul > li:first-child { + font-size: 32px; + font-weight: 600; } + #research .inner > .rnd_schedule > ul > li:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; } + #research .inner > .rnd_schedule > .schedule_content { + margin-top: 30px; } + #research .inner > .rnd_schedule > .schedule_content > ul { + width: 1000px; + height: 70px; + margin-bottom: 10px; } + #research .inner > .rnd_schedule > .schedule_content > ul > li { + float: left; } + #research .inner > .rnd_schedule > .schedule_content > ul > li:first-child { + width: 270px; + height: 100%; + background-color: #1e3571; + text-align: center; + font-size: 16px; + font-weight: 600; + line-height: 70px; + color: #fff; + cursor: default; } + #research .inner > .rnd_schedule > .schedule_content > ul > li:last-child { + width: 730px; + height: 100%; + border: 1px solid #1e3571; + box-sizing: border-box; + padding: 30px; + font-size: 16px; + font-weight: 600; + line-height: 10px; + cursor: default; + transition-duration: .2s; } + #research .inner > .rnd_schedule > .schedule_content > ul > li:last-child > em { + opacity: 0; } + #research .inner > .rnd_outside { + width: 100%; + margin-top: 150px; } + #research .inner > .rnd_outside > ul > li { + float: left; } + #research .inner > .rnd_outside > ul > li:first-child { + font-size: 32px; + font-weight: 600; } + #research .inner > .rnd_outside > ul > li:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; } + #research .inner > .rnd_outside > ol { + margin-top: 30px; + width: 100%; } + #research .inner > .rnd_outside > ol > li { + float: left; + width: 300px; + height: 570px; + background-repeat: no-repeat; + background-size: cover; } + #research .inner > .rnd_outside > ol > li:nth-child(1) { + background-image: url(../images/thief.png); + background-position: 24% 50%; } + #research .inner > .rnd_outside > ol > li:nth-child(2) { + background-image: url(../images/lamp.jpg); + background-position: 60% 50%; } + #research .inner > .rnd_outside > ol > li:nth-child(3) { + background-image: url(../images/auto_btn.png); + background-position: 50% 50%; } + #research .inner > .rnd_outside > ol > li:nth-child(4) { + background-image: url(../images/hemet.jpg); + background-position: 45% 50%; } + #research .inner > .rnd_outside > ol > li > dl { + opacity: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.6); + color: #fff; + text-align: center; + cursor: default; } + #research .inner > .rnd_outside > ol > li > dl > dt { + position: relative; + padding-top: 150px; + font-size: 25px; } + #research .inner > .rnd_outside > ol > li > dl > dt:after { + position: absolute; + top: 190px; + left: 50%; + transform: translateX(-50%); + width: 20px; + height: 1px; + background-color: #fff; + content: ''; } + #research .inner > .rnd_outside > ol > li > dl > dd { + padding: 30px 30px 0 30px; + font-size: 14px; + text-align: left; + line-height: 1.6em; } } +/*사업영역*/ +#business { + width: 100%; + background-color: white; } + #business > .inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; } + #business > .inner > h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; } + #business > .inner > h2:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #business > .inner p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; } + #business > .category { + width: 100%; + border-bottom: 1px solid #eee; } + #business > .category > ul { + margin: 0 auto; + width: 850px; } + #business > .category > ul > li { + float: left; + width: 24%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 3px; + background-color: #ddd; + color: #555; + cursor: pointer; } + #business > .category > ul > li:last-child { + margin-right: 0; } + #business > .category > ul > li:hover { + color: #fff; + background-color: #1e3571; } + #business > .category > ul > li.on { + color: #fff; + background-color: #1e3571; } + #business > .business { + padding-top: 130px; + width: 100%; + background-image: url(../images/bus_bg.jpg); } + #business > .business > div { + width: 100%; } + #business > .business > div > ul > li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #business > .business > div > ul > li:first-child { + text-indent: -99999px; } + #business > .business > div > ul > li:last-child { + height: 240px; + margin-top: 120px; } + #business > .business > div > ul > li:last-child > dl { + padding-left: 100px; } + #business > .business > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 40px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #business > .business > div > ul > li:last-child > dl > dt:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #business > .business > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #1e3571; + font-weight: 500; } + #business > .business > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #business > .business > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #1e3571; + border-radius: 7px; + content: ''; } + #business > .business > div.business_01 > ul > li:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; } + #business > .business > div.business_02 > ul > li:first-child { + background-image: url(../images/bigdata.jpg); + background-size: contain; } + #business > .business > div.business_03 > ul > li:first-child { + background-image: url(../images/soc.jpg); + background-size: contain; + background-repeat: no-repeat; } + #business > .business > div.business_04 { + padding-bottom: 100px; } + #business > .business > div.business_04 > ul > li:first-child { + background-image: url(../images/si.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 0 88%; } + +@media screen and (max-width: 768px) { + #business { + width: 100%; + background-color: white; } + #business > .inner { + height: 50px; + padding-top: 60px; + margin: 0 auto 130px; } + #business > .inner > h2 { + position: relative; + text-align: center; + font-size: 22px; + font-weight: 600; + margin-bottom: 50px; } + #business > .inner > h2:after { + position: absolute; + top: 50px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted #ffc700; + content: ''; } + #business > .inner p { + text-align: center; + font-size: 15px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; } + #business > .category { + position: fixed; + bottom: 0; + width: 100%; + border-bottom: 1px solid #ddd; + z-index: 99999; } + #business > .category > ul { + margin: 0 auto; + width: 100%; } + #business > .category > ul > li { + float: left; + width: 25%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px; + background-color: #eee; + color: #555; + cursor: pointer; } + #business > .category > ul > li:last-child { + margin-right: 0; + border-bottom: none; } + #business > .category > ul > li:hover { + color: #fff; + background-color: #1e3571; } + #business > .category > ul > li.on { + color: #fff; + background-color: #1e3571; } + #business > .business { + padding-top: 0px; + width: 100%; + background-image: url(../images/bus_bg.jpg); } + #business > .business > div { + width: 100%; + margin-top: 30px; } + #business > .business > div:first-child { + margin-top: 0; } + #business > .business > div > ul > li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; } + #business > .business > div > ul > li:first-child { + height: 200px; + float: inherit !important; + text-indent: -99999px; } + #business > .business > div > ul > li:last-child { + height: auto; + margin-top: 20px; } + #business > .business > div > ul > li:last-child > dl { + width: 90%; + padding-left: 0px; + margin: 0 auto; } + #business > .business > div > ul > li:last-child > dl > dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; } + #business > .business > div > ul > li:last-child > dl > dt:after { + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: #ffc700; + content: ''; } + #business > .business > div > ul > li:last-child > dl > dt > span { + padding-left: 4px; + font-size: 16px; + color: #1e3571; + font-weight: 500; } + #business > .business > div > ul > li:last-child > dl > dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; } + #business > .business > div > ul > li:last-child > dl > dd > br { + display: none; } + #business > .business > div > ul > li:last-child > dl > dd:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: #1e3571; + border-radius: 7px; + content: ''; } + #business > .business > div.business_01 > ul > li:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; } + #business > .business > div.business_02 > ul > li:first-child { + background-image: url(../images/bigdata.jpg); + background-size: contain; } + #business > .business > div.business_03 > ul > li:first-child { + background-image: url(../images/soc.jpg); + background-size: cover; + background-repeat: no-repeat; } + #business > .business > div.business_04 { + padding-bottom: 40px; } + #business > .business > div.business_04 > ul > li:first-child { + background-image: url(../images/si.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 90%; } } +#faq { + position: relative; + width: 100%; + margin-bottom: 60px; + height: 550px; + background-color: #fff; } + #faq > .inner { + width: 1000px; + margin: 0 auto; } + #faq > .inner > .faq_info { + float: left; + width: 450px; + margin: 0 auto; } + #faq > .inner > .faq_info > ul { + margin-top: 80px; + width: 100%; } + #faq > .inner > .faq_info > ul > li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; } + #faq > .inner > .faq_info > ul > li:last-child { + margin-top: 50px; + font-size: 17px; + color: #1e3571; + font-weight: 600; } + #faq > .inner > .faq_info > ul > li > span { + font-size: 20px; + font-weight: 600; } + #faq > .inner > .faq_info > ul > li > em { + color: #eee; } + #faq > .inner > .faq_info > ul > li.faq_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #faq > .inner > .faq_info > ul > li.faq_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #faq > .inner > .map > iframe { + float: right; + margin-top: 50px; + width: 540px; + height: 430px; + frameborder: 0; + border: 0 allowfullscreen; } + +@media screen and (max-width: 768px) { + #faq { + position: relative; + width: 100%; + padding-bottom: 60px; + margin-bottom: 0px; + height: auto; + background-color: #fff; } + #faq > .inner { + width: 100%; + margin: 0 auto; } + #faq > .inner > .faq_info { + float: inherit; + width: 90%; + margin: 0 auto; } + #faq > .inner > .faq_info > ul { + margin-top: 80px; + width: 100%; } + #faq > .inner > .faq_info > ul > li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; } + #faq > .inner > .faq_info > ul > li:last-child { + border-top: 1px dotted #ddd; + margin-top: 20px; + padding-top: 10px; + font-size: 14px; + color: #1e3571; + font-weight: 600; } + #faq > .inner > .faq_info > ul > li > span { + font-size: 17px; + font-weight: 600; } + #faq > .inner > .faq_info > ul > li > em { + color: #eee; } + #faq > .inner > .faq_info > ul > li.faq_info_main { + position: relative; + text-align: center; + font-size: 22px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #faq > .inner > .faq_info > ul > li.faq_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #faq > .inner > .map > iframe { + float: inherit; + margin-top: 20px; + width: 100%; + height: 430px; + frameborder: 0; + border: 0 allowfullscreen; } } +/*반응형*/ +.pos_right { + background-color: red; } + .pos_right > dl > dt:after { + left: 200px; } + +/*# sourceMappingURL=style_eng.css.map */ diff --git a/eng/css/style_eng.css.map b/eng/css/style_eng.css.map new file mode 100644 index 0000000..75199e6 --- /dev/null +++ b/eng/css/style_eng.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["style_eng.scss"], +"names": [], +"file": "style_eng.css" +} \ No newline at end of file diff --git a/eng/css/style_eng.scss b/eng/css/style_eng.scss new file mode 100644 index 0000000..70585b8 --- /dev/null +++ b/eng/css/style_eng.scss @@ -0,0 +1,2746 @@ +$point-color : #1e3571; +$point-color2 : #ffc700; + +/*일반현황*/ + +.index_tap { + width: 100%; + height: 35px; + border-bottom : 1px solid #eee; + background-color: #ffffff; + + >p { + margin: 0 auto; + width: 1000px; + font-size: 13px; + line-height: 35px; + text-align: right; + color: #333; + + >em { + padding: 0 3px; + font-weight: 900; + color: $point-color2; + + } + >span { + + >a { + color: #222; + font-weight: 900; + + &:hover { + text-decoration: underline; + } + } + } + }//end of p +}//end of index_tap + +@media screen and(max-width : 768px) {/*index_tap 768px 반응형*/ + + + .index_tap { + width: 100%; + height: 35px; + border-bottom : 1px solid #eee; + background-color: #ffffff; + + >p { + margin: 0 auto; + width: 100%; + font-size: 13px; + line-height: 35px; + text-align: center;//변경 + color: #333; + + >em { + padding: 0 3px; + font-weight: 900; + color: $point-color2; + + } + >span { + + >a { + padding-right: 240px;//추가 + color: #222; + font-weight: 900; + + &:hover { + text-decoration: underline; + } + } + } + }//end of p + }//end of index_tap + + + +}//index_tap 768px 반응형 + +.index_tap2 { + background-color: transparent; + border-bottom: 1px solid #e1e1e1; +} + +#status { + width: 100%; + margin-bottom: 60px; + //background-color: green; + height: 1350px; + background-color: #fff; + + + >.status { + position: relative; + width: 1000px; + margin: 0 auto 100px; + + >ul { + margin-top: 60px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 20px; + font-weight: 700; + color: $point-color; + margin-bottom: 70px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 85px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #eee; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >ol { + margin-top: 50px; + color: #bbb; + line-height: 1.4em; + + >li{ + + font-size: 13px; + + &:first-child { + font-size: 18px; + margin-bottom: 10px; + } + }//end of li + }//end of ol + + &:after { + position: absolute; + top: 120px; + right: 0; + width: 260px; + height: 345px; + + background-image: url(../images/company_3.png); + background-repeat: no-repeat; + background-position: 0 100%; + background-size: contain; + content: ''; + } + }//end of status + + >.organiz { + width: 100%; + height: 700px; + //background-color: ; + + + + >.inner { + position: relative; + width: 1000px; + height: 600px; + + + >h2 { + width: 1000px; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: $point-color; + margin-bottom:0px; + } + + >.orgimg { + width: 100%; + height: 100%; + background-image: url(../images/organiz.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; + } + + &:after { + position: absolute; + top : 65px; + width: 1000px; + height: 1px; + background-color: #ddd; + content: ''; + } + } + + >.org_eng { + position: relative; + width: 1000px; + height: 600px; + background-image: url(../images/organiz_eng.jpg); + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; + + >h2 { + width: 1000px; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: $point-color; + margin-bottom:0px; + } + + &:after { + position: absolute; + top : 65px; + width: 1000px; + height: 1px; + background-color: #ddd; + content: ''; + } + } + }//end of organiz + + + +}//end of status + + +@media screen and(max-width : 768px) { //status 768px 반응형 + + #status { + width: 100%; + margin-bottom: 0px;//변경 + padding-bottom: 60px; + //background-color: green; + height: auto; + background-color: #fff; + + + >.status { + position: relative; + width: 90%;//변경 + padding-bottom: 50px;//c추가 + margin: 0 auto 0px;//변경 + + >ul { + margin-top: 60px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 20px; + font-weight: 700; + color: $point-color; + margin-bottom: 70px; + line-height: 1.3em; + + >br { + display: none; + } + + &:after { + position: absolute; + top: 85px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #eee; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >ol { + margin-top: 50px; + color: #bbb; + line-height: 1.4em; + + >li{ + + font-size: 13px; + + &:first-child { + font-size: 18px; + margin-bottom: 10px; + } + }//end of li + }//end of ol + + &:after { + display: none; + position: absolute; + top: 120px; + right: 0; + width: 260px; + height: 345px; + + background-image: url(../images/company_3.png); + background-repeat: no-repeat; + background-position: 0 100%; + background-size: contain; + content: ''; + } + }//end of status + + >.organiz { + //display: none; + width: 100%; + height: 400px; + //background-color: ; + + + + >.inner { + position: relative; + width: 350px;//변경 + height: 350px;//변경 + background-image: none;//추가 + + + >h2 { + width: 100%;//변경 + margin: 0 auto; + text-align: left; + font-size: 25px; + color: $point-color; + margin-bottom:0px; + + } + + + + >.orgimg_kr{ + width: 100%; + background-image: url(../images/organiz_kor_m.jpg); + //background-color: green; + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; + } + + >.orgimg_eng{ + width: 100%; + background-image: url(../images/organiz_m.jpg); + //background-color: green; + background-size: contain; + background-position: 50% 100%; + background-repeat: no-repeat; + } + + &:after { + //display: none; + position: absolute; + top : -30px; + left: 50%;//추가 + transform: translateX(-50%); + width: 90%; + height: 1px; + background-color: #ddd; + content: ''; + } + } + + >.org_eng { + //display: none; + width: 100%; + height: 400px; + //background-color: ; + + >h2 { + width: 100%; + margin: 0 auto; + text-align: left; + font-size: 25px; + color: $point-color; + margin-bottom:0px; + } + + &:after { + position: absolute; + top : -25px; + width: 90%; + height: 1px; + background-color: #ddd; + content: ''; + } + } + }//end of organiz + + + + }//end of status + +}//status 768px 반응형 + + + +/*연혁*/ + + +#since { + width: 100%; + margin-bottom: 60px; + //background-color: green; + + + height: 750px; + background-color: #fff; + + + >.since { + position: relative; + width: 1000px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ + }//end of ceo_info_main + + >em { + color: $point-color2; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + + >.since_info { + width: 100%; + //background-color: orange; + + >h2 { + padding-left: 100px; + font-size: 50px; + font-weight: 500; + font-style : italic; + letter-spacing: -4px; + color: #eee; + + } + + >div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; + + >ul { + padding-left: 150px; + width: 100%; + + >li { + float: left; + margin-left: 230px; + line-height: 2.5em; + + &:first-child { + font-size: 40px; + font-weight: 900; + color: #ddd; + }//end of all li:first-child + + >dl { + padding: 5px 10px; + width: 100%; + //background-color: red; + + + >dd { + position: relative; + font-size: 16px; + font-weight: 600; + + &:after { + position: absolute; + top: 50%; + transform: translateY(-50%); + left: -20px; + width: 10px; + height: 10px; + border-radius: 15px; + background-color: $point-color2; + content: ''; + } + }//end of all dd + }//end of all dl + + }//end of all li + }//end of all ul + }//end of all div + + >.january { + + >ul { + //background-color: pink; + }//end of ul + }//end of january + + >.february { + + >ul { + //background-color: green; + }//end of ul + }//end of february + + >.march { + + >ul { + //background-color: rgb(0, 186, 191); + }//end of ul + }//end of march + }//end of since_info + + }//end of ceo_info + +}//end of since + +@media screen and(max-width : 768px) {/*since 768px 반응형*/ + + #since { + width: 100%; + margin-bottom: 0px;//변경 + padding-bottom: 80px;//추가 + //background-color: green; + + + height: auto;//변경 + background-color: #fff; + + + >.since { + position: relative; + width: 90%; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 22px;//변경 + font-weight: 600;//변경 + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + + /* &:before { + position: absolute; + top: 0px; + right: 30px; + width: 50px; + height: 50px; + background-image: url(../images/house.png); + background-repeat: no-repeat; + background-size: contain; + background-position: 50% 50%; + content: ''; + }//house + */ + }//end of ceo_info_main + + >em { + color: $point-color2; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + + >.since_info { + width: 100%; + //background-color: orange; + + >h2 { + padding-bottom: 20px;//추가 + padding-left: 0px;//변경 + font-size: 50px; + font-weight: 500; + font-style : italic; + letter-spacing: -4px; + color: #eee; + + } + + >div { + width: 100%; + margin: 10px auto 0; + border-bottom: 1px dotted #ddd; + + >ul { + padding-left: 0px;//변경 + width: 100%; + + >li { + float: inherit; + margin-left: 0px;//변경 + line-height: 1.45em; + + &:first-child { + display: none; + font-size: 40px; + font-weight: 900; + color: #ddd; + }//end of all li:first-child + + >dl { + padding: 5px 0px;//변경 + width: 100%; + //background-color: red; + + + >dd { + position: relative; + font-size: 14px; + font-weight: 500; + padding-bottom: 10px;//추가 + + &:after { + position: absolute; + top: 11px; + transform: translateY(-50%); + left: -10px; + width: 5px; + height: 5px; + border-radius: 15px; + background-color: $point-color2; + content: ''; + } + }//end of all dd + }//end of all dl + + }//end of all li + }//end of all ul + }//end of all div + + >.january { + + >ul { + //background-color: pink; + }//end of ul + }//end of january + + >.february { + + >ul { + //background-color: green; + }//end of ul + }//end of february + + >.march { + + >ul { + //background-color: rgb(0, 186, 191); + }//end of ul + }//end of march + }//end of since_info + + }//end of ceo_info + + }//end of since + + + +}//since 768px 반응형 + + +/*보유인증현황*/ + + +#certificate { + width: 100%; + margin-bottom: 0 auto; + //background-color: green; + height: 1700px; + background-color: #fff; + + + >.certificate { + position: relative; + width: 1000px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #ddd; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >.certificate_info { + width: 100%; + //background-color: green; + + >div { + width: 100%; + + >ul { + + >li { + float: left; + margin: 0 47px 50px 0; + width: 300px; + height: 400px; + //background-color: pink; + border: 1px dotted #eee; + + &:last-child { + margin-right: 0; + } + + >dl { + + >dt { + width: 300px; + height: 350px; + text-indent: -99999px; + //background-color: orange; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + } + >dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; + } + }//end of all dl + }//end of all li + }//end of all ul + }//end of all div + + + >.sect01 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); + } + + }//end of sect01 img + + >.sect02 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); + } + + }//end of sect02 img + + + >.sect03 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); + } + &:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; + } + &:nth-child(3) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_09.png); + background-position: 50% 50%; + } + + + }//end of sect03 img + + }//end of certificate_info--> + + }//end of ceo_info + +}//end of certificate + + +@media screen and(max-width : 768px) {/*certificate 768px 반응형*/ + + + #certificate { + width: 100%;//변경 + //padding-bottom: 60px; + margin-bottom: 0 auto 0;//변경 + //background-color: green; + height: auto;//변경 + background-color: #fff; + + >.index_tap { + >p { + >span { + + >a { + padding-right: 240px; + } + } + } + } + + + >.certificate { + position: relative; + width: 100%; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + width: 100%;//추가 + text-align: center; + margin-top: 20px; + font-size: 15px; + font-weight: 600; + color: #333; + line-height: 2em; + + &.status_info_main { + position: relative; + font-size: 22px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + + >em { + color: #ddd; + }//end of em + >span { + font-size: 20px; + } + }//end of li + }//end of ul + + >.certificate_info { + width: 100%; + //background-color: green; + + >div { + width: 100%; + + >ul { + width: 100%;//추가 + + >li { + float: inherit; + margin: 0 0px 50px 0; + width: 100%; + height: 400px; + //background-color: pink; + border: 1px dotted #eee; + border-top: none;//추가 + border-left: none;//추가 + border-right: none;//추가 + + &:last-child { + margin-right: 0; + } + + >dl { + + >dt { + width: 100%; + height: 350px; + text-indent: -99999px; + //background-color: orange; + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: contain; + } + >dd { + font-size: 15px; + font-weight: 600; + text-align: center; + line-height: 50px; + } + }//end of all dl + }//end of all li + }//end of all ul + }//end of all div + + + >.sect01 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_01.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_02.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_03.png); + } + + }//end of sect01 img + + >.sect02 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_04.png); + } + &:nth-child(2) > dl > dt { + background-image: url(../images/certificate_05.png); + } + &:nth-child(3) > dl > dt { + background-image: url(../images/certificate_06.png); + } + + }//end of sect02 img + + + >.sect03 >ul >li { + + &:nth-child(1) > dl > dt { + background-image: url(../images/certificate_07.png); + } + &:nth-child(2) > dl > dt { + background-size: contain; + background-image: url(../images/certificate_08.png); + background-position: 50% 50%; + } + + + }//end of sect03 img + + }//end of certificate_info--> + + }//end of ceo_info + + }//end of certificate + + +}//certificate 768px 반응형 + +#research { + width: 100%; + height: 3500px; + margin-bottom: 0 auto; + //background-color: green; + background-color: #fff; + background-image: url(../images/bus_bg.jpg); + background-repeat: repeat-Y; + + .research { + width: 100%; + height: 400px; + margin-bottom: 40px; + background-color: #fff; + + + >.inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + }//end of class research + + .inner { + + + >.rndSys { + width: 100%; + //background-color: green; + + >.camera { + margin: 0 auto; + width: 900px; + height: 600px; + background-image: url(../images/camera.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + }//end of camera + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + + } + + } + }//ednd of ul + + .rndSys_info { + padding-top: 10px; + line-height: 1.5em; + color: #aaa; + cursor: default; + }//end of rndSys_info + }//end of rndSys + + + + .strength { + margin-top: 150px; + width: 100%; + + >.strength_box1 { + float: left; + width: 870px; + height: 560px; + //background-color: orange; + + >ul { + padding: 50px 0 0 30px; + //background-color: orange; + + >li { + float: left; + + + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >.strength_top { + margin-top: 50px; + padding-left: 30px; + width: 870px; + height: 200px; + //background-color: green; + + >ul { + >li { + float: left; + width: 415px; + height: 200px; + + &:first-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_01.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_터널 유고영상 빅데이터 확보 + + &:last-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_02.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_현존하는 시스템의 한계극복기능 + + >dl { + width: 100%; + + >dt { + width: 415px; + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {/*아이콘의 공통 스타일*/ + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + }//end of first-child + + &:last-child {/*아이콘 옆 글자*/ + + >dl { + padding-left: 15px; + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 10px 0; + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_top + + >.strength_bot { + padding-left: 30px; + width: 870px; + height: 200px; + //background-color: green; + + >ul { + >li { + float: left; + width: 415px; + height: 200px; + + &:first-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_03.png); + }//우수한 경제성 아이콘 + + }//end of ul li:first-child_우수한 경제성 아이콘 + + &:last-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_04.png); + }//지속적인 기술력 성장 아이콘 + + }//end of ul li:first-child_속적인 기술력 성장 아이콘 + + >dl { + width: 100%; + + >dt { + width: 415px; + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {/*아이콘의 공통 스타일*/ + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + }//end of first-child + + &:last-child {/*아이콘 옆 글자*/ + + >dl { + padding-left: 15px; + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 10px 0; + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_bot + + }//end of strength_box1 + + >.strength_box2 { + float: left; + width: 330px; + height: 560px; + background-image: url(../images/strength.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 0; + + }//end of strength_box2 + + + }//end of strength + + + >.rnd_schedule { + width: 100%; + margin-top: 150px; + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//end of ul + + >.schedule_content { + margin-top: 30px; + + >ul { + width: 1000px; + height: 70px; + margin-bottom: 10px; + //background-color: orange; + + >li { + float: left; + + &:first-child { + width: 270px; + height: 100%; + background-color: #1e3571; + text-align: center; + font-size: 16px; + font-weight: 600; + line-height: 70px; + color: #fff; + cursor: default; + }//end of 스케쥴 제목 + + &:last-child { + width: 730px; + height: 100%; + border: 1px solid #1e3571; + box-sizing: border-box; + padding: 30px; + font-size: 16px; + font-weight: 600; + line-height: 10px; + cursor: default; + transition-duration: .2s; + + >em { + opacity: 0; + } + }//end of 스케쥴 제목 + + }//end of li + }//end of ul + }//end of schedule_content + + + + + }//end of rnd_schedule + + + >.rnd_outside { + width: 100%; + margin-top: 150px; + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >ol { + margin-top: 30px; + width: 100%; + + >li { + float: left; + width: 300px; + height: 570px; + background-repeat: no-repeat; + background-size: cover; + + &:nth-child(1) { + background-image: url(../images/thief.png); + background-position:24% 50%; + } + &:nth-child(2) { + background-image: url(../images/lamp.jpg); + background-position:60% 50%; + } + &:nth-child(3) { + background-image: url(../images/auto_btn.png); + background-position:50% 50%; + } + &:nth-child(4) { + background-image: url(../images/hemet.jpg); + background-position:45% 50%; + } + + >dl { + opacity: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.6); + color: #fff; + text-align: center; + cursor: default; + + >dt { + position: relative; + padding-top: 150px; + font-size: 25px; + + &:after { + position: absolute; + top: 190px; + left: 50%; + transform: translateX(-50%); + width: 20px; + height: 1px; + background-color: #fff; + content: ''; + } + } + + >dd { + padding: 30px 30px 0 30px; + font-size: 14px; + text-align: left; + line-height: 1.6em; + } + } + }//end of li + } + + }//end of rnd_outside + }//end of inner + +}//end of #research + +/*연구개발 모바일버전*/ + +@media screen and(max-width : 768px) { + #research { + width: 100%; + height: auto;//m + margin-bottom: 0 auto; + //background-color: green; + background-color: #fff; + background-image: url(../images/bus_bg.jpg); + background-repeat: repeat-Y; + + .research { + width: 100%; + height: 400px; + margin-bottom: 40px; + background-color: #fff; + + + >.inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + }//end of class research + + .inner { + + + >.rndSys { + width: 100%; + //background-color: green; + + >.camera { + margin: 0 auto; + width: 100%;//m + height: 600px; + background-image: url(../images/camera.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: contain;//m + }//end of camera + + >ul { + //background-color: orange; + + >li { + float: inherit;//m + + &:first-child { + font-size: 32px; + font-weight: 600; + padding: 0 10px 0 10px;//m + + } + &:last-child { + display: none;//m + font-size: 16px; + padding-top: 5px;//m + padding-left: 10px;//m + padding-right: 10px;//m + + } + + } + }//ednd of ul + + .rndSys_info { + padding-top: 10px; + padding: 10px;//m + line-height: 1.5em; + color: #aaa; + cursor: default; + }//end of rndSys_info + }//end of rndSys + + + + .strength { + margin-top: 150px; + width: 100%; + + >.strength_box1 { + float: left; + width: 870px; + height: 560px; + //background-color: orange; + + >ul { + padding: 50px 0 0 30px; + //background-color: orange; + + >li { + float: left; + + + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >.strength_top { + margin-top: 50px; + padding-left: 30px; + width: 870px; + height: 200px; + //background-color: green; + + >ul { + >li { + float: left; + width: 415px; + height: 200px; + + &:first-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_01.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_터널 유고영상 빅데이터 확보 + + &:last-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_02.png); + }//터널 유고영상 빅데이터 확보 아이콘 + + }//end of ul li:first-child_현존하는 시스템의 한계극복기능 + + >dl { + width: 100%; + + >dt { + width: 415px; + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {/*아이콘의 공통 스타일*/ + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + }//end of first-child + + &:last-child {/*아이콘 옆 글자*/ + + >dl { + padding-left: 15px; + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 10px 0; + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_top + + >.strength_bot { + padding-left: 30px; + width: 870px; + height: 200px; + //background-color: green; + + >ul { + >li { + float: left; + width: 415px; + height: 200px; + + &:first-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_03.png); + }//우수한 경제성 아이콘 + + }//end of ul li:first-child_우수한 경제성 아이콘 + + &:last-child { + + >dl>dt>ol>li:first-child { + background-image: url(../images/strength_04.png); + }//지속적인 기술력 성장 아이콘 + + }//end of ul li:first-child_속적인 기술력 성장 아이콘 + + >dl { + width: 100%; + + >dt { + width: 415px; + height: 60px; + //background-color: gray; + + >ol { + + >li { + float: left; + + &:first-child {/*아이콘의 공통 스타일*/ + width: 50px; + height: 50px; + text-indent: -99999px; + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 50%; + }//end of first-child + + &:last-child {/*아이콘 옆 글자*/ + + >dl { + padding-left: 15px; + >dt { + font-size: 17px; + font-weight: 600; + padding : 5px 0 10px 0; + cursor: default; + } + >dd { + font-size: 13px; + font-weight: 500; + cursor: default; + }//end of dl_strength + + >.line { + margin-top: 7px; + width: 0px; + height: 7px; + background-color: orange; + }//end of line + }//end of dl + }//end of last-child + + }//end of dt > ol > li + }//end of ol + } + >dd { + padding : 10px 0 0 65px; + font-size: 15px; + line-height: 1.45em; + color: #d1d1d1; + transition: .3s; + cursor: default; + }//end of + }//end of dl + }//end of li + }//end of ul + + }//end of strength_bot + + }//end of strength_box1 + + >.strength_box2 { + float: left; + width: 330px; + height: 560px; + background-image: url(../images/strength.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 50% 0; + + }//end of strength_box2 + + + }//end of strength + + + >.rnd_schedule { + width: 100%; + margin-top: 150px; + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//end of ul + + >.schedule_content { + margin-top: 30px; + + >ul { + width: 1000px; + height: 70px; + margin-bottom: 10px; + //background-color: orange; + + >li { + float: left; + + &:first-child { + width: 270px; + height: 100%; + background-color: #1e3571; + text-align: center; + font-size: 16px; + font-weight: 600; + line-height: 70px; + color: #fff; + cursor: default; + }//end of 스케쥴 제목 + + &:last-child { + width: 730px; + height: 100%; + border: 1px solid #1e3571; + box-sizing: border-box; + padding: 30px; + font-size: 16px; + font-weight: 600; + line-height: 10px; + cursor: default; + transition-duration: .2s; + + >em { + opacity: 0; + } + }//end of 스케쥴 제목 + + }//end of li + }//end of ul + }//end of schedule_content + + + + + }//end of rnd_schedule + + + >.rnd_outside { + width: 100%; + margin-top: 150px; + //background-color: green; + + >ul { + //background-color: orange; + + >li { + float: left; + + &:first-child { + font-size: 32px; + font-weight: 600; + } + &:last-child { + font-size: 16px; + padding-top: 15px; + padding-left: 3px; + } + + } + }//ednd of ul + + >ol { + margin-top: 30px; + width: 100%; + + >li { + float: left; + width: 300px; + height: 570px; + background-repeat: no-repeat; + background-size: cover; + + &:nth-child(1) { + background-image: url(../images/thief.png); + background-position:24% 50%; + } + &:nth-child(2) { + background-image: url(../images/lamp.jpg); + background-position:60% 50%; + } + &:nth-child(3) { + background-image: url(../images/auto_btn.png); + background-position:50% 50%; + } + &:nth-child(4) { + background-image: url(../images/hemet.jpg); + background-position:45% 50%; + } + + >dl { + opacity: 0; + width: 100%; + height: 100%; + background-color: rgba(0,0,0,0.6); + color: #fff; + text-align: center; + cursor: default; + + >dt { + position: relative; + padding-top: 150px; + font-size: 25px; + + &:after { + position: absolute; + top: 190px; + left: 50%; + transform: translateX(-50%); + width: 20px; + height: 1px; + background-color: #fff; + content: ''; + } + } + + >dd { + padding: 30px 30px 0 30px; + font-size: 14px; + text-align: left; + line-height: 1.6em; + } + } + }//end of li + } + + }//end of rnd_outside + }//end of inner + + }//end of #research + +}//end of research 모바일 + + + +/*사업영역*/ + +#business { + width: 100%; + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + height: 100px; + padding-top: 130px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 35px; + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 60px; + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 17px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + >.category { + width: 100%; + border-bottom: 1px solid #eee; + //ackground-color: green; + + >ul { + margin: 0 auto; + width: 850px; + + + >li { + float: left; + width: 24%; + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 3px; + background-color: #ddd; + color: #555; + cursor: pointer; + + &:last-child { + margin-right: 0; + } + + &:hover { + color:#fff; + background-color: $point-color; + } + + &.on { + color:#fff; + background-color: $point-color; + } + + + }//end of li + }//end of ul + }//end of category + + >.business { + padding-top: 130px; + width: 100%; + background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + //margin-top: 60px; + + >ul { + //background-color: green; + >li { + float: left; + width: 50%; + height: 450px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + text-indent: -99999px; + + + } + + &:last-child { + + height: 240px; + margin-top: 120px; + //background-color: red; + + + >dl{ + padding-left: 100px; + >dt { + position: relative; + font-size: 40px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + position: absolute; + top: 60px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.business_01 { + >ul >li { + + &:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_02 { + >ul >li { + + &:first-child { + background-image: url(../images/bigdata.jpg); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_03 { + >ul >li { + + &:first-child { + background-image: url(../images/soc.jpg); + background-size: contain; + background-repeat: no-repeat; + //background-color: orange; + } + }//end of 01 li + }//end of business_01 + + &.business_04 { + padding-bottom: 100px; + >ul >li { + + &:first-child { + background-image: url(../images/si.jpg); + background-size: cover; + background-repeat: no-repeat; + background-position: 0 88%; + //background-color: pink; + } + }//end of 01 li + }//end of business_01 + }//end of all div + + }//end of class business +}//end of #business + +@media screen and(max-width : 768px) {//business 768px 반응형 + + #business { + width: 100%; + + //height: 2460px; + background-color: rgb(255, 255, 255); + + >.inner { + height: 50px; + padding-top: 60px; + margin: 0 auto 130px; + //background-color: orange; + + >h2 { + position: relative; + text-align: center; + font-size: 22px;//변경 + font-weight: 600; + margin-bottom: 50px; + + &:after { + position: absolute; + top: 50px;//변경 + left: 50%; + transform: translate(-50%, -50%); + width: 120px; + height: 4px; + border: 3px dotted $point-color2; + content: ''; + } + } + p { + text-align: center; + font-size: 15px; + letter-spacing: -1px; + color: #999; + line-height: 1.45em; + } + }//end of inner + + >.category { + position: fixed;//추가 + bottom: 0;//추가 + width: 100%; + border-bottom: 1px solid #ddd;//변경 + z-index: 99999; + //ackground-color: green; + + >ul { + margin: 0 auto; + width: 100%;//변경 + + + >li { + float: left;//변경 + width: 25%;//변경 + height: 40px; + line-height: 40px; + text-align: center; + font-weight: 600; + margin-right: 0px;//변경 + background-color: #eee; + //border-bottom: 1px solid #555; + + color: #555; + cursor: pointer; + + &:last-child { + margin-right: 0; + border-bottom: none; + } + + &:hover { + color:#fff; + background-color: $point-color; + } + + &.on { + color:#fff; + background-color: $point-color; + } + + + }//end of li + }//end of ul + }//end of category + + >.business { + padding-top: 0px;//변경 + width: 100%; + background-image: url(../images/bus_bg.jpg); + + + >div { + width: 100%; + margin-top: 30px;//추가 + + &:first-child { + margin-top: 0; + } + + + >ul { + //background-color: green; + >li { + float: inherit; + width: 100%; + height: 550px; + background-size: contain; + background: no-repeat; + background-position: 50% 50%; + + &:first-child { + height: 200px; + float: inherit!important;//추가 + text-indent: -99999px; + + + } + + &:last-child { + height: auto; + margin-top: 20px;//변경 + //background-color: red; + + + >dl{ + width: 90%;//추기 + padding-left: 0px; + margin: 0 auto;//추가 + >dt { + position: relative; + font-size: 30px; + font-weight: 500; + margin-bottom: 30px; + color: #333; + + &:after { + position: absolute; + top: 50px; + left: 0; + width: 60px; + height: 4px; + background-color: $point-color2; + content: ''; + } + + >span { + padding-left: 4px; + font-size: 16px; + color: $point-color; + font-weight: 500; + //letter-spacing: -8px; + } + }//end of all dt + + >dd { + position: relative; + line-height: 2em; + padding-left: 20px; + color: #aaa; + + >br { + display: none; + } + + &:after { + position: absolute; + top: 18px; + left: 5px; + transform: translateY(-50%); + width: 5px; + height: 5px; + background-color: $point-color; + border-radius: 7px; + content: ''; + } + }//end of dd + } + }//end of all li:last-child + + + }//end of li + }//end of all ul + + &.business_01 { + >ul >li { + + &:first-child { + background-image: url(../images/business_ai2.png); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_02 { + + >ul >li { + + &:first-child { + + background-image: url(../images/bigdata.jpg); + background-size: contain; + //background-color: green; + } + }//end of 01 li + }//end of business_01 + + &.business_03 { + >ul >li { + + &:first-child { + background-image: url(../images/soc.jpg); + background-size: cover; + background-repeat: no-repeat; + //background-color: orange; + } + }//end of 01 li + }//end of business_01 + + &.business_04 { + + padding-bottom: 40px;//변경 + >ul >li { + + &:first-child { + background-image: url(../images/si.jpg); + background-size: cover;//변경 + background-repeat: no-repeat; + background-position: 50% 90%; + //background-color: pink; + } + }//end of 01 li + }//end of business_01 + }//end of all div + + }//end of class business + }//end of #business + +}//business 768px 반응형 + + + +#faq { + position: relative; + width: 100%; + margin-bottom: 60px; + //background-color: green; + height: 550px; + background-color: #fff; + + + >.inner { + width: 1000px; + margin: 0 auto; + + >.faq_info { + float: left; + width: 450px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + + &:last-child { + margin-top: 50px; + font-size: 17px; + color: $point-color; + font-weight: 600; + } + + >span { + font-size: 20px; + font-weight: 600; + } + + >em { + color: #eee; + } + + &.faq_info_main { + position: relative; + font-size: 29px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + } + }//end of ul + }//end of ceo_info + >.map>iframe { + float: right; + margin-top: 50px; + width : 540px; + height : 430px; + frameborder : 0; + border : 0 allowfullscreen; + } + + }//end of inner + + +}//end of faq + +@media screen and(max-width : 768px) {//faq768px 반응형 + + #faq { + position: relative; + width: 100%; + padding-bottom: 60px; + margin-bottom: 0px;//변경 + //background-color: green; + height: auto; + background-color: #fff; + + + >.inner { + width: 100%;//변경 + margin: 0 auto; + + >.faq_info { + float: inherit;//변경 + width: 90%; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + + &:last-child { + border-top: 1px dotted #ddd;//추가 + margin-top: 20px;//변경 + padding-top: 10px;//추가 + font-size: 14px; + color: $point-color; + font-weight: 600; + } + + >span { + font-size: 17px; + font-weight: 600; + } + + >em { + color: #eee; + } + + &.faq_info_main { + position: relative; + text-align: center;//추가 + font-size: 22px;//변경 + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + } + }//end of ul + }//end of ceo_info + >.map>iframe { + float: inherit;//변경 + margin-top: 20px; + width : 100%; + height : 430px; + frameborder : 0; + border : 0 allowfullscreen; + } + + }//end of inner + + + }//end of faq + +}//faq 768px 반응형 + + + +/*반응형*/ +.pos_right { + background-color: red; + //text-align: right; + + >dl { + + + >dt { + &:after { + left: 200px; + } + } + } + + + +}//end of pos_right diff --git a/eng/css/sub.css b/eng/css/sub.css new file mode 100644 index 0000000..65802a9 --- /dev/null +++ b/eng/css/sub.css @@ -0,0 +1,314 @@ +@charset "UTF-8"; +#topic_bg { + width: 100%; } + #topic_bg > .topic_bg_info { + width: 100%; + height: 300px; + background-image: url(../images/ceo.jpg); + background-position: 50% 40%; + background-repeat: no-repeat; + background-size: cover; } + #topic_bg > .topic_bg_info > ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; } + #topic_bg > .topic_bg_info > ul > li { + color: #fff; } + #topic_bg > .topic_bg_info > ul > li:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; } + #topic_bg > .topic_bg_info > ul > li:first-child > span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: #ffc700; } + #topic_bg > .topic_bg_info > ul > li:last-child { + font-size: 13px; } + +@media screen and (max-width: 768px) { + /*topic bg 768px 반응형*/ + #topic_bg { + width: 100%; } + #topic_bg > .topic_bg_info { + width: 100%; + height: 300px; + background-image: url(../images/ceo.jpg); + background-position: 50% 40%; + background-repeat: no-repeat; + background-size: cover; } + #topic_bg > .topic_bg_info > ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; } + #topic_bg > .topic_bg_info > ul > li { + color: #fff; } + #topic_bg > .topic_bg_info > ul > li:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; } + #topic_bg > .topic_bg_info > ul > li:first-child > span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: #ffc700; } + #topic_bg > .topic_bg_info > ul > li:last-child { + font-size: 13px; } } +.topic2_bg { + width: 100%; + height: 300px; + background-image: url(../images/topic05_bg.jpg); + background-position: 50% 20%; + background-repeat: no-repeat; + background-size: cover; } + .topic2_bg > ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; } + .topic2_bg > ul > li { + color: #fff; } + .topic2_bg > ul > li:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; } + .topic2_bg > ul > li:first-child > span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: #ffc700; } + .topic2_bg > ul > li:last-child { + font-size: 13px; } + +@media screen and (max-width: 768px) { + /*topic2 subbg 768px 반응형*/ + .topic2_bg { + width: 100%; + height: 300px; + background-image: url(../images/topic05_bg.jpg); + background-position: 50% 20%; + background-repeat: no-repeat; + background-size: cover; } + .topic2_bg > ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; } + .topic2_bg > ul > li { + color: #fff; } + .topic2_bg > ul > li:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; } + .topic2_bg > ul > li:first-child > span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: #ffc700; } + .topic2_bg > ul > li:last-child { + font-size: 13px; } } +.topic3_bg { + width: 100%; + height: 300px; + background-image: url(../images/question2.jpg); + background-position: 50% 15%; + background-repeat: no-repeat; + background-size: cover; } + .topic3_bg > ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; } + .topic3_bg > ul > li { + color: #fff; } + .topic3_bg > ul > li:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; } + .topic3_bg > ul > li:first-child > span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: #ffc700; } + .topic3_bg > ul > li:last-child { + font-size: 13px; } + +#ceo { + width: 100%; + margin-bottom: 60px; + height: 700px; + background-color: #fff; } + #ceo > .index_tap { + width: 100%; + height: 35px; + border-bottom: 1px solid #eee; + background-color: #ffffff; } + #ceo > .index_tap > p { + margin: 0 auto; + width: 1000px; + font-size: 13px; + line-height: 35px; + text-align: right; + color: #333; } + #ceo > .index_tap > p > em { + padding: 0 3px; + font-weight: 900; + color: #ffc700; } + #ceo > .index_tap > p > span > a { + color: #222; + font-weight: 900; } + #ceo > .index_tap > p > span > a:hover { + text-decoration: underline; } + #ceo > .ceo_info { + position: relative; + width: 1000px; + margin: 0 auto; } + #ceo > .ceo_info > ul { + margin-top: 80px; + width: 100%; } + #ceo > .ceo_info > ul > li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + text-align: justify; } + #ceo > .ceo_info > ul > li.ceo_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #ceo > .ceo_info > ul > li.ceo_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #ceo > .ceo_info:after { + position: absolute; + top: 100px; + right: 0; + width: 300px; + height: 445px; + background-image: url(../images/ceo_bg.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + content: ''; } + #ceo .all_employees { + position: absolute; + bottom: -40px; + left: 50%; + font-size: 18px; + font-weight: 600; } + #ceo .all_employees_eng { + display: none; + position: absolute; + bottom: -20px; + left: 50%; + font-size: 18px; + font-weight: 600; } + +@media screen and (max-width: 768px) { + /*CEO 768px 반응형*/ + #ceo { + width: 100%; + padding-bottom: 100px; + margin-bottom: 0px; + height: auto; + background-color: #fff; } + #ceo > .index_tap { + width: 100%; + height: 35px; + border-bottom: 1px solid #eee; + background-color: #ffffff; } + #ceo > .index_tap > p { + margin: 0 auto; + width: 100%; + font-size: 13px; + line-height: 35px; + padding-left: 0px; + text-align: center; + color: #333; } + #ceo > .index_tap > p > em { + padding: 0 3px; + font-weight: 900; + color: #ffc700; } + #ceo > .index_tap > p > span > a { + padding-right: 240px; + color: #222; + font-weight: 900; } + #ceo > .index_tap > p > span > a:hover { + text-decoration: underline; } + #ceo > .ceo_info { + position: relative; + width: 90%; + margin: 0 auto; } + #ceo > .ceo_info > ul { + margin-top: 80px; + width: 100%; } + #ceo > .ceo_info > ul > li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + text-align: left; } + #ceo > .ceo_info > ul > li > br { + display: none; } + #ceo > .ceo_info > ul > li.ceo_info_main { + text-align: center; + position: relative; + font-size: 22px; + font-weight: 700; + color: #1e3571; + margin-bottom: 55px; + line-height: 1.3em; } + #ceo > .ceo_info > ul > li.ceo_info_main > span { + display: block; } + #ceo > .ceo_info > ul > li.ceo_info_main:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; } + #ceo > .ceo_info:after { + display: none; + position: absolute; + top: 100px; + right: 0; + width: 300px; + height: 445px; + background-image: url(../images/ceo_bg.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + content: ''; } + #ceo .all_employees { + position: absolute; + bottom: -40px; + left: 50%; + font-size: 18px; + font-weight: 600; } + #ceo .all_employees_eng { + display: none; + position: absolute; + bottom: -20px; + left: 50%; + font-size: 18px; + font-weight: 600; } } + +/*# sourceMappingURL=sub.css.map */ diff --git a/eng/css/sub.css.map b/eng/css/sub.css.map new file mode 100644 index 0000000..c513bf1 --- /dev/null +++ b/eng/css/sub.css.map @@ -0,0 +1,7 @@ +{ +"version": 3, +"mappings": "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", +"sources": ["sub.scss"], +"names": [], +"file": "sub.css" +} \ No newline at end of file diff --git a/eng/css/sub.scss b/eng/css/sub.scss new file mode 100644 index 0000000..bfc2ae3 --- /dev/null +++ b/eng/css/sub.scss @@ -0,0 +1,484 @@ +$point-color : #1e3571; +$point-color2 : #ffc700; + +#topic_bg { + //padding-top: 70px;//메뉴만큼 띄우기 + width: 100%; + //background-color: green; + + + + >.topic_bg_info { + width: 100%; + height: 300px; + background-image: url(../images/ceo.jpg); + background-position: 50% 40%; + background-repeat: no-repeat; + background-size: cover; + + >ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; + + + //background-color: green; + + >li { + color: #fff; + + &:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; + + >span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: $point-color2; + } + }//end of li:first + + &:last-child { + font-size: 13px; + }//end of li:last + } + }//end of ul + }//end of topic_bg_info + +}//end of topic_bg + + +@media screen and(max-width : 768px) {/*topic bg 768px 반응형*/ + + #topic_bg { + //padding-top: 70px;//메뉴만큼 띄우기 + width: 100%; + //background-color: green; + + + + >.topic_bg_info { + width: 100%; + height: 300px; + background-image: url(../images/ceo.jpg); + background-position: 50% 40%; + background-repeat: no-repeat; + background-size: cover; + + >ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; + + + //background-color: green; + + >li { + color: #fff; + + &:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; + + >span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: $point-color2; + } + }//end of li:first + + &:last-child { + font-size: 13px; + }//end of li:last + } + }//end of ul + }//end of topic_bg_info + + }//end of topic_bg + +}//topic bg 768px 반응형 + + + +.topic2_bg { + width: 100%; + height: 300px; + background-image: url(../images/topic05_bg.jpg); + background-position: 50% 20%; + background-repeat: no-repeat; + background-size: cover; + + >ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; + + + //background-color: green; + + >li { + color: #fff; + + &:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; + + >span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: $point-color2; + } + }//end of li:first + + &:last-child { + font-size: 13px; + }//end of li:last + } + }//end of ul +}//end of topic2sub_bg + +@media screen and(max-width : 768px) { /*topic2 subbg 768px 반응형*/ + + .topic2_bg { + width: 100%; + height: 300px; + background-image: url(../images/topic05_bg.jpg); + background-position: 50% 20%; + background-repeat: no-repeat; + background-size: cover; + + >ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; + + + //background-color: green; + + >li { + color: #fff; + + &:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; + + >span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: $point-color2; + } + }//end of li:first + + &:last-child { + font-size: 13px; + }//end of li:last + } + }//end of ul + }//end of topic2sub_bg + +}//topic2 subbg 768px 반응형 + +.topic3_bg { + width: 100%; + height: 300px; + background-image: url(../images/question2.jpg); + background-position: 50% 15%; + background-repeat: no-repeat; + background-size: cover; + + >ul { + opacity: 0; + margin: 0 auto; + padding-top: 160px; + width: 100%; + text-align: center; + + + //background-color: green; + + >li { + color: #fff; + + &:first-child { + font-size: 35px; + font-weight: 700; + padding-bottom: 7px; + + >span { + margin-left: 3px; + font-size: 13px; + font-weight: 600; + color: $point-color2; + } + }//end of li:first + + &:last-child { + font-size: 13px; + }//end of li:last + } + }//end of ul +}//end of topic3_bg + +#ceo { + width: 100%; + margin-bottom: 60px; + height: 700px; + background-color: #fff; + //background-color: green; + + >.index_tap { + width: 100%; + height: 35px; + border-bottom : 1px solid #eee; + background-color: #ffffff; + + >p { + margin: 0 auto; + width: 1000px; + font-size: 13px; + line-height: 35px; + text-align: right; + color: #333; + + >em { + padding: 0 3px; + font-weight: 900; + color: $point-color2; + + } + >span { + + >a { + color: #222; + font-weight: 900; + + &:hover { + text-decoration: underline; + } + } + } + }//end of p + }//end of index_tap + + + + + + >.ceo_info { + position: relative; + width: 1000px; + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + text-align: justify; + + &.ceo_info_main { + position: relative; + font-size: 30px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + } + }//end of ul + + &:after { + position: absolute; + top: 100px; + right: 0; + width: 300px; + height: 445px; + background-image: url(../images/ceo_bg.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + content: ''; + } + }//end of ceo_info + + .all_employees { + position: absolute; + bottom: -40px; + left: 50%; + font-size: 18px; + font-weight: 600; + }//end of all_employees + .all_employees_eng { + display: none; + position: absolute; + bottom: -20px; + left: 50%; + font-size: 18px; + font-weight: 600; + }//end of all_employees + +}//end of CEO + + +@media screen and(max-width : 768px) {/*CEO 768px 반응형*/ + + #ceo { + width: 100%; + padding-bottom: 100px; + margin-bottom: 0px; + height: auto; + background-color: #fff; + //background-color: green; + + >.index_tap { + width: 100%;//변경 + height: 35px; + border-bottom : 1px solid #eee; + background-color: #ffffff; + + >p { + margin: 0 auto; + width: 100%; + font-size: 13px; + line-height: 35px; + padding-left: 0px; + text-align: center;//변경 + color: #333; + + >em { + padding: 0 3px; + font-weight: 900; + color: $point-color2; + + } + >span { + + >a {padding-right: 240px; + color: #222; + font-weight: 900; + + &:hover { + text-decoration: underline; + } + } + } + }//end of p + }//end of index_tap + + + + + + >.ceo_info { + position: relative; + width: 90%;//변경 + margin: 0 auto; + + >ul { + margin-top: 80px; + width: 100%; + //background-color: green; + >li { + margin-top: 20px; + font-size: 14px; + font-weight: 500; + color: #333; + line-height: 1.7em; + text-align: left; + + >br { + display: none; + } + + &.ceo_info_main { + text-align: center; + position: relative; + font-size: 22px; + font-weight: 700; + color: $point-color; + margin-bottom: 55px; + line-height: 1.3em; + + >span { + display: block; + } + + &:after { + position: absolute; + top: 65px; + left: 0; + width: 100%; + height: 1px; + background-color: #ddd; + content: ''; + } + }//end of ceo_info_main + } + }//end of ul + + &:after { + display: none;//변경 + position: absolute; + top: 100px; + right: 0; + width: 300px; + height: 445px; + background-image: url(../images/ceo_bg.png); + background-repeat: no-repeat; + background-position: 50% 50%; + background-size: cover; + content: ''; + } + }//end of ceo_info + + .all_employees { + position: absolute; + bottom: -40px; + left: 50%; + font-size: 18px; + font-weight: 600; + }//end of all_employees + .all_employees_eng { + display: none; + position: absolute; + bottom: -20px; + left: 50%; + font-size: 18px; + font-weight: 600; + }//end of all_employees + + }//end of CEO + + +}//CEO 768px 반응형 diff --git a/eng/html/index_eng.html b/eng/html/index_eng.html new file mode 100644 index 0000000..bd7a30d --- /dev/null +++ b/eng/html/index_eng.html @@ -0,0 +1,395 @@ + + + + + + + DBNtect + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    +
    +

    Main page.

    +
    +
      +
    • img1
    • +
    • img2
    • +
    • img3
    • +
    • img4
    • +
    +
    +
    +
      +
    • +
      +
      INNOVATION
      +
      + We constantly seek newness for valuable
      + change and innovation +
      +
      +
    • +
    • +
      +
      PASSION
      +
      + We are always passionate
      + about customer convenience +
      +
      +
    • +
    • +
      +
      CHALLANGE
      +
      + We Do not settle for the present and
      continue to + grow through new challenges +
      +
      +
    • +
    • +
      +
      TECHNOLOGY
      +
      + we are make plan for technology
      + to change world. only us +
      +
      +
    • +
    +
    +
    +

    prev

    +

    next

    +
    + +

    +
    +
    +

    about company.

    +
    +

    company

    +
    + +
    + +
    +
    +
      +
    • +
      +
      Innovator to create future value
      +
      DBN-tech
      +
      +
    • +
    +
      +
    1. +
      +
      We will strive to become a human-centered
      +
      technology company that creates new value
      +
      through infinite passion and constant challenge
      +
      +
    2. +
    + +
    + + +
    + +
    + +
    + +
    +
    +
      +
    • +
      +
      8
      +
      Certificate
      +
      +
    • +
    • +
      +
      18.01.05
      +
      Date of Establishment
      +
      +
    • +
    • +
      +
      3
      +
      Progress project
      +
      +
    • +
    +
    +
    + + + + +
    +

    Service.

    +
    +

    BUSINESS

    +
    +
    + +
    +
      +
    • +
      +
      +

      icon1

      +
      +
      AI
      +
      + Machine learning based processing system
      + Deep Learning Based Object Recognition System
      + Deep Learning Image Processing Infrastructure Management +
      +
      Discovery more
      +
      +
    • +
    • +
      +
      +

      icon2_1

      +
      +
      Public Big Data
      +
      + visualization of big-data in numeric, letters
      + consulting on collection, processing, analysis
      + Solution development and consulting + +
      +
      Discovery more
      +
      +
    • + +
    • +
      +
      +

      icon1

      +
      +
      SOCs Technical support
      +
      + Traffic video processing and
      status informatization service
      + Monitoring of image and informatization of
      status ofinfra-structures and SOCfacilities
      + +
      +
      Discovery more
      +
      +
    • +
    • +
      +
      +

      icon1

      +
      +
      SI & ITO
      +
      + Financial, public, telecommunications, service sector
      + System and platform construction and operation
      + E-Commerce, SNS, ERP, Enterprise Business Support
      Establish and operate online platform such as solution
      +
      +
      Discovery more
      +
      +
    • + +
    +
    + + + +
    + + +
    + +
    +

    prev

    +

    next

    +
    +
    + + +
    + + + +
    +

    come.

    +

    contact

    + +
    +
    +
    + +
    +
    +
      +
    • + Address 155-11, Robot land-ro, Seo-gu, Incheon, Republic of Korea +
    • +
    • + +
    • + +
    +
    +
    + + +
    + +
    + + + + + + + + + diff --git a/eng/html/sub01_1_eng.html b/eng/html/sub01_1_eng.html new file mode 100644 index 0000000..f491eb5 --- /dev/null +++ b/eng/html/sub01_1_eng.html @@ -0,0 +1,189 @@ + + + + + + + DBNtect + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • COMPANYGreetings
    • +
    • We will be a leader in creating future value
    • +
    +
    + + + +
    + +
    + +
    +

    COMPANY > Greatings

    +
    + +
    +
      +
    • “We will be a leader in creating future value.”
    • +
    • + We are a start-up company like Supernova, which was founded on January 5, 2018, to develop and
      + provide new and useful public information services in conjunction with massive public big-data. +
    • + And we are developing a deep-learning based image analysis solution
      + in conjunction with public SOC CCTVs currently in operation. +
    • +
    • + Through keeping research and development for tomorrow new services, we intend to become an
      + "global public technology oriented corporation" optimized in the age of the 4th industrial revolution,
      + which can contribute to the intelligent information service of national SOC management system. +
    • +
    • + By providing efficient and affordable solutions, we are also enhancing our position as a professional solutions
      + developer in a public SI field, making us a next generation technology-based
      + technology innovator in the coming age of the 4th industrial revolution(or INDUSTRY 4.0 ERA) +
    • +
    • + Finally, We are a HumanTechnology Company. It is a company that seeks technology and prosperity in
      + our lives, and wants to create a company inspired by our customers and people-centric thinking. +
    • +
    • + We look forward to receiving more attention and supports from you.
      +
    • +
    • Thank you.
    • +
    +
    + + +
    + + + +
    + + diff --git a/eng/html/sub01_2_eng.html b/eng/html/sub01_2_eng.html new file mode 100644 index 0000000..35efe20 --- /dev/null +++ b/eng/html/sub01_2_eng.html @@ -0,0 +1,197 @@ + + + + + + + DBNtect + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • COMPANYStatus
    • +
    • You can see our general situation
    • +
    +
    + + + +
    + +
    + +
    +

    COMPANY > Status

    +
    + +
    +
      +
    • + "DBN-tech is committed to the potential value of information
      It is a specialized IT company that grasps and provides high quality information." +
    • +
    • + Corporate Name | DBN-tech. Ltd. +
    • +
    • + CEO | Ja-Young, Choi +
    • +
    • + Date of Establishment | 05 January 2018 +
    • +
    • + Business | AI, Public Big Data, Technical Ssupport, SI & ITO +
    • +
    • + Address of Head Office | 478 Jonggeundang Bldg. No. 206, Baekbeom-ro
      + 472-gu, Bupyeong-gu, Incheon, Korea +
    • +
    • + Business license number | 704-88-00959 +
    • +
    + +
    + +
    + +
    +

    Organization

    +

    + + +
    +
    + + +
    + + + +
    + + diff --git a/eng/html/sub01_3_eng.html b/eng/html/sub01_3_eng.html new file mode 100644 index 0000000..0e93bd9 --- /dev/null +++ b/eng/html/sub01_3_eng.html @@ -0,0 +1,209 @@ + + + + + + + DBNtect + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • COMPANYStatus
    • +
    • You can check our history
    • +
    +
    + + + +
    + +
    + +
    +

    COMPANY > History

    +
    + +
    +
      +
    • + "We are constantly preparing to jump higher." +
    • +
    +
    +

    HISTORY

    +
    +
      +
    • +
    • +
      +
      Jan. 2018 - The establishment of a company (Corporate registration number : 120111 - *******)
      +
      Jan. 2018 - Business license registration (North Incheon tax office : 704-88-*****)
      +
      Jan. 2018 - Certification of small and medium business identification (SMB:0010-****-**)
      +
      Jan. 2018 - Registration for a software operator (Korean Software Industry Association : B18-******)
      +
      Jan. 2018 - Acquisition of the direct production certificate (KBIZ : 2038-0071-*****)
      +
      Jan. 2018 - Registration for qualification for a bid participation in government ordering business
      +
      Jan. 2018 - Accreditation of the Research and Development Authority (Korea Industrial Technology Association : 2018150584)
      +
      +
    • +
    +
    +
    +
      +
    • +
    • +
      +
      Feb. 2018 - cquisition of the Female-owned business certification (Incheon Regional Small and Medium Business Administration : 0116-188-*****)
      + +
      +
    • +
    +
    +
    +
      +
    • +
    • +
      +
      Mar. 2018 - Program Registration(Korean Copyright Commission : Machine Learning Based Big-Data Analysis System)
      + +
      +
    • +
    +
    +
    + + +
    + +
    + + + +
    + + diff --git a/eng/html/sub01_4_eng.html b/eng/html/sub01_4_eng.html new file mode 100644 index 0000000..63d41fd --- /dev/null +++ b/eng/html/sub01_4_eng.html @@ -0,0 +1,236 @@ + + + + + + + DBNtect + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • COMPANYCertification
    • +
    • You can check the status of our certification
    • +
    +
    + + + +
    + +
    + +
    +

    COMPANY > Certification

    +
    + +
    +
      +
    • + "This is the certificate." +
    • +
    +
    +
    +
      +
    • +
      +
      사업자등록증 사진
      +
      Business license
      +
      +
    • +
    • +
      +
      SW사업자신고확인서 사진
      +
      SW Operator Report Certificate
      +
      +
    • +
    • +
      +
      기업연구소 사진
      +
      R&D Center Certificate
      +
      +
    • +
    +
    +
    +
      +
    • +
      +
      직접생산확인증명서 사진
      +
      Direct production Certificate
      +
      +
    • +
    • +
      +
      중소기업확인서 사진
      +
      SMB identification Certificate
      +
      +
    • +
    • +
      +
      경쟁입찰참가자격증등록 사진
      +
      Registration of participation in competitive bidding
      +
      +
    • +
    +
    +
    +
      +
    • +
      +
      여성기업확인서 사진
      +
      Female company certificate
      +
      +
    • +
    • +
      +
      프로그램등록증 사진
      +
      Program Certificate
      +
      +
    • +
    • +
      +
      벤처기업확인서 사진
      +
      Venture Business certificate
      +
      +
    • +
    +
    +
    + + +
    + +
    + + + +
    + + diff --git a/eng/html/sub01_4_eng.html.18.07.10.bak b/eng/html/sub01_4_eng.html.18.07.10.bak new file mode 100644 index 0000000..a6a4b3e --- /dev/null +++ b/eng/html/sub01_4_eng.html.18.07.10.bak @@ -0,0 +1,231 @@ + + + + + + + DBNtect + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • COMPANYCertification
    • +
    • You can check the status of our certification
    • +
    +
    + + + +
    + +
    + +
    +

    COMPANY > Certification

    +
    + +
    +
      +
    • + "This is the certificate." +
    • +
    +
    +
    +
      +
    • +
      +
      사업자등록증 사진
      +
      Business license
      +
      +
    • +
    • +
      +
      SW사업자신고확인서 사진
      +
      SW Operator Report Certificate
      +
      +
    • +
    • +
      +
      기업연구소 사진
      +
      R&D Center Certificate
      +
      +
    • +
    +
    +
    +
      +
    • +
      +
      직접생산확인증명서 사진
      +
      Direct production Certificate
      +
      +
    • +
    • +
      +
      중소기업확인서 사진
      +
      SMB identification Certificate
      +
      +
    • +
    • +
      +
      경쟁입찰참가자격증등록 사진
      +
      Registration of participation in competitive bidding
      +
      +
    • +
    +
    +
    +
      +
    • +
      +
      여성기업확인서 사진
      +
      Female company certificate
      +
      +
    • + +
    +
    +
    + + +
    + +
    + + + +
    + + diff --git a/eng/html/sub01_4_eng.html.18.07.12.bak b/eng/html/sub01_4_eng.html.18.07.12.bak new file mode 100644 index 0000000..859d49d --- /dev/null +++ b/eng/html/sub01_4_eng.html.18.07.12.bak @@ -0,0 +1,231 @@ + + + + + + + DBNtect + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • COMPANYCertification
    • +
    • You can check the status of our certification
    • +
    +
    + + + +
    + +
    + +
    +

    COMPANY > Certification

    +
    + +
    +
      +
    • + "This is the certificate." +
    • +
    +
    +
    +
      +
    • +
      +
      사업자등록증 사진
      +
      Business license
      +
      +
    • +
    • +
      +
      SW사업자신고확인서 사진
      +
      SW Operator Report Certificate
      +
      +
    • +
    • +
      +
      기업연구소 사진
      +
      R&D Center Certificate
      +
      +
    • +
    +
    +
    +
      +
    • +
      +
      직접생산확인증명서 사진
      +
      Direct production Certificate
      +
      +
    • +
    • +
      +
      중소기업확인서 사진
      +
      SMB identification Certificate
      +
      +
    • +
    • +
      +
      경쟁입찰참가자격증등록 사진
      +
      Registration of participation in competitive bidding
      +
      +
    • +
    +
    +
    +
      +
    • +
      +
      여성기업확인서 사진
      +
      Female company certificate
      +
      +
    • +
    • +
      +
      프로그램등록증 사진
      +
      Program Certificate
      +
      +
    • +
    +
    +
    + + +
    + +
    + + + +
    + + diff --git a/eng/html/sub01_5_eng.html b/eng/html/sub01_5_eng.html new file mode 100644 index 0000000..7e10ce8 --- /dev/null +++ b/eng/html/sub01_5_eng.html @@ -0,0 +1,165 @@ + + + + + + + + DBNtect + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • COMPANYR&D
    • +
    • Our R&D Plan
    • +
    +
    + + + +
    + +
    + +
    +

    COMPANY > R&D

    +
    + +
    + coming soon. +
    + + + +
    + + + +
    + + diff --git a/eng/html/sub01_5_eng.html.18.07.23 b/eng/html/sub01_5_eng.html.18.07.23 new file mode 100644 index 0000000..c05213f --- /dev/null +++ b/eng/html/sub01_5_eng.html.18.07.23 @@ -0,0 +1,229 @@ + + + + + + + + DBNtect + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • COMPANYR&D
    • +
    • Our R&D Plan
    • +
    +
    + + + +
    + +
    + +
    +

    COMPANY > R&D

    +
    + +
    +

    + Research & Develop +

    +
    +
      +
    • < Deep-learning based incident detection system >
    • +
    • < Bridge and facility physical examination system >
    • +
    • < Lunar surface Crater detection system >
    • +
    +
    +
    + +
    +
    +
      +
    • img01
    • +
    • +
      +
      01. Deep-learning based incident detection system
      +
      + Deep-learning based incident detection system is Automatically recognizes targets within range +and Automaticlly alert and observing Emergency situation. +Compared with computer vision based images analysis , It was less influenced by weather and region. +Can recognized Accident more high accuracy. +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      02. Bridge and facility physical examination system
      +
      + Social infrastructure in Korea has grown rapidly in the 1970s. +Currently, facilities that are more than 30 years old account for about 10%, and in 2025 they will exceed 20%. +So, maintenance costs for older facilities are increasing, and the need for a solution based on computer image +recognition has been continuously raised for effective facility condition assessment and safety diagnosis. +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      03. Lunar surface Crater detection system
      +
      + It is very important to collect terrain information based on images acquired from the lunar. +in the lunar surface research. As the development of deep learning technology, +research is being carried out to apply this technology to terrain information collection. +We are in the process of studying image object segmentation together with KICT space construction research center group. +
      +
    • +
    +
    +
    + + + + + + + + +
    + + + +
    + + diff --git a/eng/html/sub01_5_eng.html.bak b/eng/html/sub01_5_eng.html.bak new file mode 100644 index 0000000..9ca37f9 --- /dev/null +++ b/eng/html/sub01_5_eng.html.bak @@ -0,0 +1,416 @@ + + + + + + + + DBNtect + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • COMPANYR&D
    • +
    • Our R&D Plan
    • +
    +
    + + + +
    + +
    + +
    +

    COMPANY > R&D

    +
    + +
    +
    +

    + R&D +

    +

    + We constantly strive for
    + future core technology research. +

    +
    +
    + +
    +
    +

    +
      +
    • Deep Learning based Tunnel Incident Detection System on CCTVS
    • +
    • Deep Learning based Tunnel Incident Detection System on CCTVS
    • +
    +

    + This System Automatically Recognizes the Target. and, + It is a System that Automatically Detects and Alerts the Situation Specified in the Management Instructions. + Existing Systems are Frequently Malfunctioned and some Tunnels are Shut Down. As a result, Purpose of Preventing Additional Accidents is Lost. +

    +
    + + + + + +
    +
    +
      +
    • Strength
    • +
    • Strength
    • +
    + +
    +
      +
    • +
      +
      +
        +
      1. icon
      2. +
      3. +
        +
        + Secured of Tunnel Accident Video +
        +
        + Strength01 +
        +
        +
        +
      4. +
      +
      +
      + Secured of Tunnel Accident Video
      + (10 Years of data) +
      +
      +
    • +
    • +
      +
      +
        +
      1. icon
      2. +
      3. +
        +
        + Obtaining to overcome of existing system +
        +
        + Strength02 +
        +
        +
        +
      4. +
      +
      +
      + - Using by Deep Learning Technology
      (Overcoming the Limits of Algorithm-based Solutions)
      + - Select of algorithms with high recognition rate
      + (Faster R-CNN : At least 10 times faster and accurate)
      + +
      +
      +
      +
    • +
    +
    +
    +
      +
    • +
      +
      +
        +
      1. icon
      2. +
      3. +
        +
        + Excellent Economic +
        +
        + Strength03 +
        +
        +
        +
      4. +
      +
      +
      + Reducing facility investment cost by optimizing
      + CCTV installation in tunnel to about 200m +
      +
      +
    • +
    • +
      +
      +
        +
      1. icon
      2. +
      3. +
        +
        + Self-study +
        +
        + Strength04 +
        +
        +
        +
      4. +
      +
      +
      + Repeat learning to improve performance automatically +
      +
      +
    • +
    +
    + +
    + +
    + +
    + +
    + + + +
    +
      +
    • Other of Availability
    • +
    • Other of Availability
    • +
    + +
    +
      +
    • Complementing deep learning algorithm
    • +
    • + - Complement the functionality of the system being developed and tested +
    • +
    +
      +
    • Making System UI
    • +
    • + - Develop interface for user's convenience +
    • +
    +
      +
    • Making Promotion website
    • +
    • + - Create a website to promote development systems and services +
    • +
    +
      +
    • Operating funds
    • +
    • + - Government funding and investment promotion plan +
    • +
    +
      +
    • Exhibition, Seminar
    • +
    • + - Developing activities to promote the development system +
    • +
    +
      +
    • Build a Test Bed and Final Verification
    • +
    • + - Final review of system environment construction and operation +
    • +
    +
      +
    • Pre-sales Promotion
    • +
    • + - Implement pilot service in tunnel and promote business to public institutions +
    • +
    +
    +
    + + +
    +
      +
    • Other of Availability
    • +
    • Other of Availability
    • +
    + +
      +
    1. +
      +
      Crime and Theft
      +
      + Can be used for crime prevention and theft +
      +
      +
    2. + +
    3. +
      +
      Public SOC
      +
      + Effective management of public management facilities +
      +
      +
    4. +
    5. +
      +
      Autonomous Driving
      +
      + Safe autonomous driving service +
      +
      +
    6. +
    7. +
      +
      Safety
      +
      + Rapid protection from unexpected danger +
      +
      +
    8. +
    + + + +
    + + +
    + +
    + + + +
    + + diff --git a/eng/html/sub02_Ai_eng.html b/eng/html/sub02_Ai_eng.html new file mode 100644 index 0000000..40ff5f1 --- /dev/null +++ b/eng/html/sub02_Ai_eng.html @@ -0,0 +1,272 @@ + + + + + + + DBNtect + + + + + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • BUSINESS
    • +
    • Our business area
    • +
    +
    +
    + +
    +
    +

    BUSINESS

    +
    +
    +

    + Recognize and apply the flow of change +

    +

    + We provide the best service to our customers with the latest technology and
    + ensure the stability of the system through continuous maintenance. +

    +
    + +
    +
      +
    • AI
    • +
    • BIGDATA
    • +
    • SOC
    • +
    • SI & ITO
    • +
    +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Artificial IntelligenceAI
      +
      + Bespoke development of documentary big-data processing and analysis systems for + customer’s needs and
      + consulting services for supporting commercialization based on machine-learning +
      +
      + Development of Real-time CCTV video object detection and pattern recognition system and +
      support consulting for 24 hours operation based on deep-learning +
      +
      + Development of monitoring system for status of national SOC structures and facilities through deep-learning
      + based image processing, and consulting service for supporting 24 hours system operation and management +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public Big DataBigData
      +
      + Developing solutions and consulting on collection, processing, analysis, visualization of big-data in numeric,
      + letters and documentary information and processing, analysis, and visualization +
      +
      + Development of statistical analysis and informatization system and operation + support services +
      +
      + Development of a public CCTV video processing and analysis system and operation + support service +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public SOCs Technical supportSupport
      +
      + Traffic video processing and status informatization service +
      +
      + Local condition monitoring and cost saving support +
      +
      + Monitoring of image and informatization of status of infra-structures and SOC + facilities (slope, tunnel, bridge, etc.) +
      +
      + Recognition and warning alarm of real-time accidents and emergency events on + public facilities and allocated area +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      System integration and operationsSI & ITO
      +
      + Building and operating of systems and platforms in financial, public, communications, and service sector +
      +
      + Building and operating of online platforms such as e-Commerce, SNS, ERP, and business support solutions for a company +
      +
      + Building and operating of various mobile systems (iOS / Android) +
      +
      + Network and video integrated security management service +
      +
      + Design and Building of Integrated Service Platform(Open API, SDP, etc.) +
      +
      +
    • +
    +
    +
    + +
    + + + +
    + + diff --git a/eng/html/sub02_Bigdata_eng.html b/eng/html/sub02_Bigdata_eng.html new file mode 100644 index 0000000..921627c --- /dev/null +++ b/eng/html/sub02_Bigdata_eng.html @@ -0,0 +1,271 @@ + + + + + + + DBNtect + + + + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • BUSINESS
    • +
    • Our business area
    • +
    +
    +
    + +
    +
    +

    BUSINESS

    +
    +
    +

    + Recognize and apply the flow of change +

    +

    + We provide the best service to our customers with the latest technology and
    + ensure the stability of the system through continuous maintenance. +

    +
    + +
    +
      +
    • AI
    • +
    • BIGDATA
    • +
    • SOC
    • +
    • SI & ITO
    • +
    +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Artificial IntelligenceAI
      +
      + Bespoke development of documentary big-data processing and analysis systems for + customer’s needs and
      + consulting services for supporting commercialization based on machine-learning +
      +
      + Development of Real-time CCTV video object detection and pattern recognition system and +
      support consulting for 24 hours operation based on deep-learning +
      +
      + Development of monitoring system for status of national SOC structures and facilities through deep-learning
      + based image processing, and consulting service for supporting 24 hours system operation and management +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public Big DataBigData
      +
      + Developing solutions and consulting on collection, processing, analysis, visualization of big-data in numeric,
      + letters and documentary information and processing, analysis, and visualization +
      +
      + Development of statistical analysis and informatization system and operation + support services +
      +
      + Development of a public CCTV video processing and analysis system and operation + support service +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public SOCs Technical supportSupport
      +
      + Traffic video processing and status informatization service +
      +
      + Local condition monitoring and cost saving support +
      +
      + Monitoring of image and informatization of status of infra-structures and SOC + facilities (slope, tunnel, bridge, etc.) +
      +
      + Recognition and warning alarm of real-time accidents and emergency events on + public facilities and allocated area +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      System integration and operationsSI & ITO
      +
      + Building and operating of systems and platforms in financial, public, communications, and service sector +
      +
      + Building and operating of online platforms such as e-Commerce, SNS, ERP, and business support solutions for a company +
      +
      + Building and operating of various mobile systems (iOS / Android) +
      +
      + Network and video integrated security management service +
      +
      + Design and Building of Integrated Service Platform(Open API, SDP, etc.) +
      +
      +
    • +
    +
    +
    + +
    + + + +
    + + diff --git a/eng/html/sub02_Si_Ito_eng.html b/eng/html/sub02_Si_Ito_eng.html new file mode 100644 index 0000000..43bfc92 --- /dev/null +++ b/eng/html/sub02_Si_Ito_eng.html @@ -0,0 +1,271 @@ + + + + + + + DBNtect + + + + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • BUSINESS
    • +
    • Our business area
    • +
    +
    +
    + +
    +
    +

    BUSINESS

    +
    +
    +

    + Recognize and apply the flow of change +

    +

    + We provide the best service to our customers with the latest technology and
    + ensure the stability of the system through continuous maintenance. +

    +
    + +
    +
      +
    • AI
    • +
    • BIGDATA
    • +
    • SOC
    • +
    • SI & ITO
    • +
    +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Artificial IntelligenceAI
      +
      + Bespoke development of documentary big-data processing and analysis systems for + customer’s needs and
      + consulting services for supporting commercialization based on machine-learning +
      +
      + Development of Real-time CCTV video object detection and pattern recognition system and +
      support consulting for 24 hours operation based on deep-learning +
      +
      + Development of monitoring system for status of national SOC structures and facilities through deep-learning
      + based image processing, and consulting service for supporting 24 hours system operation and management +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public Big DataBigData
      +
      + Developing solutions and consulting on collection, processing, analysis, visualization of big-data in numeric,
      + letters and documentary information and processing, analysis, and visualization +
      +
      + Development of statistical analysis and informatization system and operation + support services +
      +
      + Development of a public CCTV video processing and analysis system and operation + support service +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public SOCs Technical supportSupport
      +
      + Traffic video processing and status informatization service +
      +
      + Local condition monitoring and cost saving support +
      +
      + Monitoring of image and informatization of status of infra-structures and SOC + facilities (slope, tunnel, bridge, etc.) +
      +
      + Recognition and warning alarm of real-time accidents and emergency events on + public facilities and allocated area +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      System integration and operationsSI & ITO
      +
      + Building and operating of systems and platforms in financial, public, communications, and service sector +
      +
      + Building and operating of online platforms such as e-Commerce, SNS, ERP, and business support solutions for a company +
      +
      + Building and operating of various mobile systems (iOS / Android) +
      +
      + Network and video integrated security management service +
      +
      + Design and Building of Integrated Service Platform(Open API, SDP, etc.) +
      +
      +
    • +
    +
    +
    + +
    + + + +
    + + diff --git a/eng/html/sub02_Soc_eng.html b/eng/html/sub02_Soc_eng.html new file mode 100644 index 0000000..dc2110a --- /dev/null +++ b/eng/html/sub02_Soc_eng.html @@ -0,0 +1,271 @@ + + + + + + + DBNtect + + + + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • BUSINESS
    • +
    • Our business area
    • +
    +
    +
    + +
    +
    +

    BUSINESS

    +
    +
    +

    + Recognize and apply the flow of change +

    +

    + We provide the best service to our customers with the latest technology and
    + ensure the stability of the system through continuous maintenance. +

    +
    + +
    +
      +
    • AI
    • +
    • BIGDATA
    • +
    • SOC
    • +
    • SI & ITO
    • +
    +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Artificial IntelligenceAI
      +
      + Bespoke development of documentary big-data processing and analysis systems for + customer’s needs and
      + consulting services for supporting commercialization based on machine-learning +
      +
      + Development of Real-time CCTV video object detection and pattern recognition system and +
      support consulting for 24 hours operation based on deep-learning +
      +
      + Development of monitoring system for status of national SOC structures and facilities through deep-learning
      + based image processing, and consulting service for supporting 24 hours system operation and management +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public Big DataBigData
      +
      + Developing solutions and consulting on collection, processing, analysis, visualization of big-data in numeric,
      + letters and documentary information and processing, analysis, and visualization +
      +
      + Development of statistical analysis and informatization system and operation + support services +
      +
      + Development of a public CCTV video processing and analysis system and operation + support service +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public SOCs Technical supportSupport
      +
      + Traffic video processing and status informatization service +
      +
      + Local condition monitoring and cost saving support +
      +
      + Monitoring of image and informatization of status of infra-structures and SOC + facilities (slope, tunnel, bridge, etc.) +
      +
      + Recognition and warning alarm of real-time accidents and emergency events on + public facilities and allocated area +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      System integration and operationsSI & ITO
      +
      + Building and operating of systems and platforms in financial, public, communications, and service sector +
      +
      + Building and operating of online platforms such as e-Commerce, SNS, ERP, and business support solutions for a company +
      +
      + Building and operating of various mobile systems (iOS / Android) +
      +
      + Network and video integrated security management service +
      +
      + Design and Building of Integrated Service Platform(Open API, SDP, etc.) +
      +
      +
    • +
    +
    +
    + +
    + + + +
    + + diff --git a/eng/html/sub02_eng.html b/eng/html/sub02_eng.html new file mode 100644 index 0000000..e4a13ad --- /dev/null +++ b/eng/html/sub02_eng.html @@ -0,0 +1,271 @@ + + + + + + + DBNtect + + + + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • BUSINESS
    • +
    • Our business area
    • +
    +
    +
    + +
    +
    +

    BUSINESS

    +
    +
    +

    + Recognize and apply the flow of change +

    +

    + We provide the best service to our customers with the latest technology and
    + ensure the stability of the system through continuous maintenance. +

    +
    + +
    +
      +
    • AI
    • +
    • BIGDATA
    • +
    • SOC
    • +
    • SI & ITO
    • +
    +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Artificial IntelligenceAI
      +
      + Bespoke development of documentary big-data processing and analysis systems for + customer’s needs and
      + consulting services for supporting commercialization based on machine-learning +
      +
      + Development of Real-time CCTV video object detection and pattern recognition system and +
      support consulting for 24 hours operation based on deep-learning +
      +
      + Development of monitoring system for status of national SOC structures and facilities through deep-learning
      + based image processing, and consulting service for supporting 24 hours system operation and management +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public Big DataBigData
      +
      + Developing solutions and consulting on collection, processing, analysis, visualization of big-data in numeric,
      + letters and documentary information and processing, analysis, and visualization +
      +
      + Development of statistical analysis and informatization system and operation + support services +
      +
      + Development of a public CCTV video processing and analysis system and operation + support service +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      Public SOCs Technical supportSupport
      +
      + Traffic video processing and status informatization service +
      +
      + Local condition monitoring and cost saving support +
      +
      + Monitoring of image and informatization of status of infra-structures and SOC + facilities (slope, tunnel, bridge, etc.) +
      +
      + Recognition and warning alarm of real-time accidents and emergency events on + public facilities and allocated area +
      +
      +
    • +
    +
    +
    +
      +
    • img01
    • +
    • +
      +
      System integration and operationsSI & ITO
      +
      + Building and operating of systems and platforms in financial, public, communications, and service sector +
      +
      + Building and operating of online platforms such as e-Commerce, SNS, ERP, and business support solutions for a company +
      +
      + Building and operating of various mobile systems (iOS / Android) +
      +
      + Network and video integrated security management service +
      +
      + Design and Building of Integrated Service Platform(Open API, SDP, etc.) +
      +
      +
    • +
    +
    +
    + +
    + + + +
    + + diff --git a/eng/html/sub03_eng.html b/eng/html/sub03_eng.html new file mode 100644 index 0000000..2d5e465 --- /dev/null +++ b/eng/html/sub03_eng.html @@ -0,0 +1,199 @@ + + + + + + + DBNtect + + + + + + + + + + + + +
    +

    +
    +
    +

    버튼

    +

    dbntect

    +
    + +
    + Language + +
    +
    +
    +
    +
    + + +
    + +
    +
      +
    • CONTACT
    • +
    • I'll teach you how to get here
    • +
    +
    + + + +
    + +
    + +
    +

    CONTACT

    +
    +
    + + +
    +
      +
    • "I'll teach you how to get here"
    • +
    • + TEL | +82 - 32 - 721 - 5670
      +
    • +
    • + Fax | +82 - 32 - 721 - 5680
      +
    • +
    • Email | ahn@dbnt.co.kr
    • +
    • Location | RobotTower, No. 1205, 155-11, Robot land-ro,
      Seo-gu, Incheon, Republic of Korea
    • +
    • + +
    • +
    +
    + + +
    +
    +
    + +
    + + +
    + + + +
    + + + + + + + + + diff --git a/eng/images/ai2.jpg b/eng/images/ai2.jpg new file mode 100644 index 0000000..110c08b Binary files /dev/null and b/eng/images/ai2.jpg differ diff --git a/eng/images/auto_btn.png b/eng/images/auto_btn.png new file mode 100644 index 0000000..cd5134f Binary files /dev/null and b/eng/images/auto_btn.png differ diff --git a/eng/images/bg_1.jpg b/eng/images/bg_1.jpg new file mode 100644 index 0000000..9c9a38a Binary files /dev/null and b/eng/images/bg_1.jpg differ diff --git a/eng/images/bg_2.png b/eng/images/bg_2.png new file mode 100644 index 0000000..9473550 Binary files /dev/null and b/eng/images/bg_2.png differ diff --git a/eng/images/bg_quote.png b/eng/images/bg_quote.png new file mode 100644 index 0000000..0324f03 Binary files /dev/null and b/eng/images/bg_quote.png differ diff --git a/eng/images/bigdata.jpg b/eng/images/bigdata.jpg new file mode 100644 index 0000000..1db69b4 Binary files /dev/null and b/eng/images/bigdata.jpg differ diff --git a/eng/images/bus_bg.jpg b/eng/images/bus_bg.jpg new file mode 100644 index 0000000..8294f2e Binary files /dev/null and b/eng/images/bus_bg.jpg differ diff --git a/eng/images/business_ai.png b/eng/images/business_ai.png new file mode 100644 index 0000000..937e1bf Binary files /dev/null and b/eng/images/business_ai.png differ diff --git a/eng/images/business_ai2.png b/eng/images/business_ai2.png new file mode 100644 index 0000000..6f4fe84 Binary files /dev/null and b/eng/images/business_ai2.png differ diff --git a/eng/images/camera.png b/eng/images/camera.png new file mode 100644 index 0000000..7ef620d Binary files /dev/null and b/eng/images/camera.png differ diff --git a/eng/images/ceo.jpg b/eng/images/ceo.jpg new file mode 100644 index 0000000..131e9e9 Binary files /dev/null and b/eng/images/ceo.jpg differ diff --git a/eng/images/ceo_bg.png b/eng/images/ceo_bg.png new file mode 100644 index 0000000..a7514b8 Binary files /dev/null and b/eng/images/ceo_bg.png differ diff --git a/eng/images/certificate_01.png b/eng/images/certificate_01.png new file mode 100644 index 0000000..5007110 Binary files /dev/null and b/eng/images/certificate_01.png differ diff --git a/eng/images/certificate_02.png b/eng/images/certificate_02.png new file mode 100644 index 0000000..4d941ee Binary files /dev/null and b/eng/images/certificate_02.png differ diff --git a/eng/images/certificate_03.png b/eng/images/certificate_03.png new file mode 100644 index 0000000..5e059ed Binary files /dev/null and b/eng/images/certificate_03.png differ diff --git a/eng/images/certificate_04.png b/eng/images/certificate_04.png new file mode 100644 index 0000000..a1dd0ca Binary files /dev/null and b/eng/images/certificate_04.png differ diff --git a/eng/images/certificate_05.png b/eng/images/certificate_05.png new file mode 100644 index 0000000..5e86c5a Binary files /dev/null and b/eng/images/certificate_05.png differ diff --git a/eng/images/certificate_06.png b/eng/images/certificate_06.png new file mode 100644 index 0000000..ec6a6c0 Binary files /dev/null and b/eng/images/certificate_06.png differ diff --git a/eng/images/certificate_07.png b/eng/images/certificate_07.png new file mode 100644 index 0000000..022f834 Binary files /dev/null and b/eng/images/certificate_07.png differ diff --git a/eng/images/certificate_08.png b/eng/images/certificate_08.png new file mode 100644 index 0000000..d908d7d Binary files /dev/null and b/eng/images/certificate_08.png differ diff --git a/eng/images/certificate_09.png b/eng/images/certificate_09.png new file mode 100644 index 0000000..e31d076 Binary files /dev/null and b/eng/images/certificate_09.png differ diff --git a/eng/images/certificate_10.png b/eng/images/certificate_10.png new file mode 100644 index 0000000..b4ef453 Binary files /dev/null and b/eng/images/certificate_10.png differ diff --git a/eng/images/company_3.png b/eng/images/company_3.png new file mode 100644 index 0000000..a54add5 Binary files /dev/null and b/eng/images/company_3.png differ diff --git a/eng/images/crack.png b/eng/images/crack.png new file mode 100644 index 0000000..9e8f745 Binary files /dev/null and b/eng/images/crack.png differ diff --git a/eng/images/f_bg.jpg b/eng/images/f_bg.jpg new file mode 100644 index 0000000..40fb922 Binary files /dev/null and b/eng/images/f_bg.jpg differ diff --git a/eng/images/f_right.png b/eng/images/f_right.png new file mode 100644 index 0000000..425ecfe Binary files /dev/null and b/eng/images/f_right.png differ diff --git a/eng/images/favicon.ico b/eng/images/favicon.ico new file mode 100644 index 0000000..d08d184 Binary files /dev/null and b/eng/images/favicon.ico differ diff --git a/eng/images/hemet.jpg b/eng/images/hemet.jpg new file mode 100644 index 0000000..27298d0 Binary files /dev/null and b/eng/images/hemet.jpg differ diff --git a/eng/images/house.png b/eng/images/house.png new file mode 100644 index 0000000..8fd5c43 Binary files /dev/null and b/eng/images/house.png differ diff --git a/eng/images/icon_1.png b/eng/images/icon_1.png new file mode 100644 index 0000000..f414c24 Binary files /dev/null and b/eng/images/icon_1.png differ diff --git a/eng/images/icon_2.png b/eng/images/icon_2.png new file mode 100644 index 0000000..d83e39a Binary files /dev/null and b/eng/images/icon_2.png differ diff --git a/eng/images/icon_3.png b/eng/images/icon_3.png new file mode 100644 index 0000000..366f7f0 Binary files /dev/null and b/eng/images/icon_3.png differ diff --git a/eng/images/icon_4.png b/eng/images/icon_4.png new file mode 100644 index 0000000..9e2cce8 Binary files /dev/null and b/eng/images/icon_4.png differ diff --git a/eng/images/icon_5.png b/eng/images/icon_5.png new file mode 100644 index 0000000..1454121 Binary files /dev/null and b/eng/images/icon_5.png differ diff --git a/eng/images/icon_6.png b/eng/images/icon_6.png new file mode 100644 index 0000000..787eadb Binary files /dev/null and b/eng/images/icon_6.png differ diff --git a/eng/images/icon_7.png b/eng/images/icon_7.png new file mode 100644 index 0000000..e505975 Binary files /dev/null and b/eng/images/icon_7.png differ diff --git a/eng/images/img01.jpg b/eng/images/img01.jpg new file mode 100644 index 0000000..7441118 Binary files /dev/null and b/eng/images/img01.jpg differ diff --git a/eng/images/intro.png b/eng/images/intro.png new file mode 100644 index 0000000..87c58c3 Binary files /dev/null and b/eng/images/intro.png differ diff --git a/eng/images/intro03.png b/eng/images/intro03.png new file mode 100644 index 0000000..53fdfab Binary files /dev/null and b/eng/images/intro03.png differ diff --git a/eng/images/lamp.jpg b/eng/images/lamp.jpg new file mode 100644 index 0000000..6821aae Binary files /dev/null and b/eng/images/lamp.jpg differ diff --git a/eng/images/logo.jpg b/eng/images/logo.jpg new file mode 100644 index 0000000..d603484 Binary files /dev/null and b/eng/images/logo.jpg differ diff --git a/eng/images/logo.png b/eng/images/logo.png new file mode 100644 index 0000000..cd55c19 Binary files /dev/null and b/eng/images/logo.png differ diff --git a/eng/images/logo_r.png b/eng/images/logo_r.png new file mode 100644 index 0000000..7138582 Binary files /dev/null and b/eng/images/logo_r.png differ diff --git a/eng/images/mVisual02.jpg b/eng/images/mVisual02.jpg new file mode 100644 index 0000000..8693e1a Binary files /dev/null and b/eng/images/mVisual02.jpg differ diff --git a/eng/images/mVisual04.jpg b/eng/images/mVisual04.jpg new file mode 100644 index 0000000..fb26f53 Binary files /dev/null and b/eng/images/mVisual04.jpg differ diff --git a/eng/images/mVisual08.jpg b/eng/images/mVisual08.jpg new file mode 100644 index 0000000..976f38d Binary files /dev/null and b/eng/images/mVisual08.jpg differ diff --git a/eng/images/m_map.png b/eng/images/m_map.png new file mode 100644 index 0000000..10fff1d Binary files /dev/null and b/eng/images/m_map.png differ diff --git a/eng/images/m_map_eng.png b/eng/images/m_map_eng.png new file mode 100644 index 0000000..1438de7 Binary files /dev/null and b/eng/images/m_map_eng.png differ diff --git a/eng/images/map.jpg b/eng/images/map.jpg new file mode 100644 index 0000000..90b0c7a Binary files /dev/null and b/eng/images/map.jpg differ diff --git a/eng/images/map_18.08.06.jpg b/eng/images/map_18.08.06.jpg new file mode 100644 index 0000000..a76a8fa Binary files /dev/null and b/eng/images/map_18.08.06.jpg differ diff --git a/eng/images/map_eng_18.08.06.jpg b/eng/images/map_eng_18.08.06.jpg new file mode 100644 index 0000000..f32207d Binary files /dev/null and b/eng/images/map_eng_18.08.06.jpg differ diff --git a/eng/images/moon.png b/eng/images/moon.png new file mode 100644 index 0000000..d7cadc7 Binary files /dev/null and b/eng/images/moon.png differ diff --git a/eng/images/next_btn.png b/eng/images/next_btn.png new file mode 100644 index 0000000..192a489 Binary files /dev/null and b/eng/images/next_btn.png differ diff --git a/eng/images/next_btn_hover.png b/eng/images/next_btn_hover.png new file mode 100644 index 0000000..9242eea Binary files /dev/null and b/eng/images/next_btn_hover.png differ diff --git a/eng/images/one.jpg b/eng/images/one.jpg new file mode 100644 index 0000000..932d7d6 Binary files /dev/null and b/eng/images/one.jpg differ diff --git a/eng/images/organiz.jpg b/eng/images/organiz.jpg new file mode 100644 index 0000000..aefa856 Binary files /dev/null and b/eng/images/organiz.jpg differ diff --git a/eng/images/organiz_eng.jpg b/eng/images/organiz_eng.jpg new file mode 100644 index 0000000..198893e Binary files /dev/null and b/eng/images/organiz_eng.jpg differ diff --git a/eng/images/organiz_kor_m.jpg b/eng/images/organiz_kor_m.jpg new file mode 100644 index 0000000..d225139 Binary files /dev/null and b/eng/images/organiz_kor_m.jpg differ diff --git a/eng/images/organiz_m.jpg b/eng/images/organiz_m.jpg new file mode 100644 index 0000000..8d91616 Binary files /dev/null and b/eng/images/organiz_m.jpg differ diff --git a/eng/images/prev_btn.png b/eng/images/prev_btn.png new file mode 100644 index 0000000..b29e52d Binary files /dev/null and b/eng/images/prev_btn.png differ diff --git a/eng/images/prev_btn_hover.png b/eng/images/prev_btn_hover.png new file mode 100644 index 0000000..d6016a0 Binary files /dev/null and b/eng/images/prev_btn_hover.png differ diff --git a/eng/images/q_icon.png b/eng/images/q_icon.png new file mode 100644 index 0000000..b5e05a7 Binary files /dev/null and b/eng/images/q_icon.png differ diff --git a/eng/images/question2.jpg b/eng/images/question2.jpg new file mode 100644 index 0000000..764bc3f Binary files /dev/null and b/eng/images/question2.jpg differ diff --git a/eng/images/research_m01.jpg b/eng/images/research_m01.jpg new file mode 100644 index 0000000..d7cd812 Binary files /dev/null and b/eng/images/research_m01.jpg differ diff --git a/eng/images/si.jpg b/eng/images/si.jpg new file mode 100644 index 0000000..4a6be2e Binary files /dev/null and b/eng/images/si.jpg differ diff --git a/eng/images/soc.jpg b/eng/images/soc.jpg new file mode 100644 index 0000000..1f5b39b Binary files /dev/null and b/eng/images/soc.jpg differ diff --git a/eng/images/strength.jpg b/eng/images/strength.jpg new file mode 100644 index 0000000..43d271f Binary files /dev/null and b/eng/images/strength.jpg differ diff --git a/eng/images/strength_01.png b/eng/images/strength_01.png new file mode 100644 index 0000000..8343332 Binary files /dev/null and b/eng/images/strength_01.png differ diff --git a/eng/images/strength_02.png b/eng/images/strength_02.png new file mode 100644 index 0000000..d6f1089 Binary files /dev/null and b/eng/images/strength_02.png differ diff --git a/eng/images/strength_03.png b/eng/images/strength_03.png new file mode 100644 index 0000000..63b5500 Binary files /dev/null and b/eng/images/strength_03.png differ diff --git a/eng/images/strength_04.png b/eng/images/strength_04.png new file mode 100644 index 0000000..bab9f22 Binary files /dev/null and b/eng/images/strength_04.png differ diff --git a/eng/images/thief.png b/eng/images/thief.png new file mode 100644 index 0000000..f2a2d0e Binary files /dev/null and b/eng/images/thief.png differ diff --git a/eng/images/toggle.png b/eng/images/toggle.png new file mode 100644 index 0000000..5cedd5b Binary files /dev/null and b/eng/images/toggle.png differ diff --git a/eng/images/toggle_cls.png b/eng/images/toggle_cls.png new file mode 100644 index 0000000..230f9fb Binary files /dev/null and b/eng/images/toggle_cls.png differ diff --git a/eng/images/topic05_bg.jpg b/eng/images/topic05_bg.jpg new file mode 100644 index 0000000..0a1a671 Binary files /dev/null and b/eng/images/topic05_bg.jpg differ diff --git a/eng/images/topic_bg.jpg b/eng/images/topic_bg.jpg new file mode 100644 index 0000000..06ef0e3 Binary files /dev/null and b/eng/images/topic_bg.jpg differ diff --git a/eng/images/up_arrow.png b/eng/images/up_arrow.png new file mode 100644 index 0000000..2194d67 Binary files /dev/null and b/eng/images/up_arrow.png differ diff --git a/eng/index.html b/eng/index.html new file mode 100644 index 0000000..8983519 --- /dev/null +++ b/eng/index.html @@ -0,0 +1,109 @@ + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • +
      +
      DETECTION
      +
      Apply various object detection models to find the objects distributed in the images, create a bounding box in real time and identify detected objects.
      + + +
      +
    • +
    • +
      +
      TRACKING
      +
      Tracking the location change of a specific object through the location information obtained from the detection phase.
      + + +
      +
    • +
    • +
      +
      주식회사 디비엔텍
      + +
      +
    • +
    +
    +
    +
    + + + +
    + + + + diff --git a/eng/js/ai.js b/eng/js/ai.js new file mode 100644 index 0000000..4d45ece --- /dev/null +++ b/eng/js/ai.js @@ -0,0 +1,15 @@ +$(function(){ + + $(window).on("load", function(){ + var nowIdx = 0; + var busArr=[]; + + $(".bs_section").each(function(idx){ + busArr[idx] = $(this).offset().top; + console.log("높이값", busArr[idx]) + })//사업영역의 해당 div의 높이값 구하기 + + $("html, body").stop().animate({"scrollTop" : busArr[nowIdx]-22},400) + }) + +}) diff --git a/eng/js/bigdata.js b/eng/js/bigdata.js new file mode 100644 index 0000000..3296383 --- /dev/null +++ b/eng/js/bigdata.js @@ -0,0 +1,15 @@ +$(function(){ + + $(window).on("load", function(){ + var nowIdx = 1; + var busArr=[]; + + $(".bs_section").each(function(idx){ + busArr[idx] = $(this).offset().top; + console.log("높이값", busArr[idx]) + })//사업영역의 해당 div의 높이값 구하기 + + $("html, body").stop().animate({"scrollTop" : busArr[nowIdx]-22},400) + }) + +}) diff --git a/eng/js/function.js b/eng/js/function.js new file mode 100644 index 0000000..149486b --- /dev/null +++ b/eng/js/function.js @@ -0,0 +1,373 @@ +$(function(){ + //console.log("hi") + var $mainMnu = $(".gnb > ul > li"); + + var $mVisual = $("#mVisual"); + var $mVisual_img = $("#mVisual").find(".mVisual_img > ul > li"); + var $mVisual_txt = $("#mVisual").find(".mVisual_txt > ul > li"); + + var $mVisual_indicator = $(".mVisual_indicator"); + var $mVisual_prev_btn = $mVisual_indicator.find(".mVisual_prev_btn"); + var $mVisual_next_btn = $mVisual_indicator.find(".mVisual_next_btn"); + + var $indicator = $(".service_indicator > ul > li"); + var $service_li = $(".service_container > div > ul > li"); + + var nowIdx = 0; + var oldIdx = nowIdx; + var headerIdx = 0; + var sectionTop = []; + + $(".section").each(function(idx){ + sectionTop[idx] = $(this).offset().top; + console.log("section", sectionTop[idx]) + }); //section의 높이값 알아내기 + + + + + + + + function nextIdx() { + if(nowIdx ==$mVisual_img.size()-1) { + nowIdx = 0; + }else { + nowIdx++; + } + }//nextIdx + + function nextFnc() { + $mVisual_img.eq(nowIdx).stop().fadeIn(400); + $mVisual_img.eq(oldIdx).stop().fadeOut(400); + $mVisual_txt.eq(nowIdx).stop().fadeIn(400); + $mVisual_txt.eq(oldIdx).stop().fadeOut(400); + + + oldIdx = nowIdx; + }//nextFnc + + function start() { + myInterval = setInterval(function(){ + nextIdx(); + nextFnc(); + },4500) + }//interval start + + function restart() { + clearInterval(myInterval) + setTimeout(function(){ + start(); + },1) + }//clearInterval and start + + + //$mVisual.height($(window).height()); + $(document).ready(function(){ + $mainMnu.find("a").eq(nowIdx).addClass("on"); + start(); + $mVisual_img.hide().eq(nowIdx).show(); + $mVisual_txt.hide().eq(nowIdx).show(); + // $("html, body").stop().animate({"scrollTop" : 0},400) + })//새로고침시 상단으로 이동 + + $(window).on("load resize", function(){ + $mVisual.height($(window).height()); + + })// window load , resize fnc + + + $(window).on("resize", function(){ + if($(window).width()<769 && $(window).width()>767) { + location.reload(); + console.log("reload") + } + })//반응형 넘어갈때 양옆 +-1로 새로고침 + + + $(window).on("load", function(){ + //$(".gnb").css({"display" : "block"}) + //$("html, body").stop().animate({"scrollTop" : 0},400) + + $indicator.eq(nowIdx).addClass("on"); + + + + $(".mVisual_indicator").on({ + "mouseover" : function(){ + clearInterval(myInterval); + $(".mVisual_txt").stop().css({"background-color" : "rgba(0,0,0,0.8)"}) + }, + "mouseleave" : function(){ + $(".mVisual_txt").stop().css({"background-color" : "rgba(0,0,0,0.6)"}) + start(); + } + }) + })// window load fnc + + $mVisual_prev_btn.on("click", function(){ + + + restart(); + + if(nowIdx == 0) { + nowIdx = $mVisual_img.size()-1; + }else { + nowIdx--; + } + + $mVisual_img.eq(nowIdx).stop().fadeIn(400); + $mVisual_img.eq(oldIdx).stop().fadeOut(400); + + $mVisual_txt.eq(nowIdx).stop().fadeIn(400); + $mVisual_txt.eq(oldIdx).stop().fadeOut(400); + + oldIdx = nowIdx; + + })//end of $mVisual_prev_btn click + + $mVisual_next_btn.on("click", function(){ + + //restart(); + nextIdx(); + nextFnc(); + + })//end of $mVisual_next_btn click + + + + + $(window).on("scroll", function(){ + + var scrollH = $(window).scrollTop(); + + if($(window).width()>768) { + if(scrollH >100) { + $(".upArrow").stop().fadeIn(400) + $("header").css({"background-color" : "#1e3571"}) + }else { + $(".upArrow").stop().fadeOut(400) + $("header").css({"background-color" : "rgba(000,000,000,0.3)"}) + }//위로 올라가기 나타남과 없어짐 + }else if($(window).width()<768) { + if(scrollH >100) { + $(".upArrow").stop().fadeIn(400) + $("header").css({"background-color" : "#1e3571"}) + }else { + $(".upArrow").stop().fadeOut(400) + $("header").css({"background-color" : "#444"}) + }//위로 올라가기 나타남과 없어짐 + } + + // if(scrollH >sectionTop[1]-200) { + // $("header").css({"background" : "#2381e3"}) //rgba(000,000,000,0.5) + // }else { + // $("header").css({"background" : "none"}) + // } + + + + $mVisual.css({"opacity" : 1-(scrollH/900)}) + + for(i=0; i<5; i++) { + if(scrollH >= sectionTop[i]-320) { + $(".gnb > ul > li").eq(i).children().addClass("on").parent().siblings().children().removeClass("on"); + } + } + + + })// upArrow 나타내기 + + $(".upArrow").on("click", function(){ + $("html, body").stop().animate({"scrollTop" : 0},400) + })//올라가기 위로 + + $(".downArrow").on("click", function(){ + $("html, body").stop().animate({"scrollTop" : sectionTop[1]-70},600) + })//home에서 아래 화살표 클릭시 이동 + + + + + + $("header").find(".headerM").on("click", function(){ + headerIdx = $(".headerM").index($(this)); + $("html, body").stop().animate({"scrollTop" : sectionTop[headerIdx]-70},600) + console.log("sectionTop", headerIdx) + //e.preventDefault(); + });//메인메뉴 클릭시 해당 section이동 + + +var flag = false; + + if($(window).width()>768) { + $(".gnb > ul > li").on("mouseover", function(){ + !flag; + headerIdx = $(".headerM").index($(this)); + $(".sub_bg").stop().slideDown(200); + $(".sub").eq(headerIdx-1).stop().slideDown(100); + if($(this).hasClass("hit")) { + flag = !flag; + $(".sub").hide(); + $(".sub_bg").stop().slideUp(100); + } + + + console.log("PC") + })//메뉴 호버 + }else { + $(".gnb > ul > li").on("click", function(){ + !flag; + headerIdx = $(".headerM").index($(this)); + //$(".sub_bg").stop().slideDown(200); + $(".sub").eq(headerIdx-1).stop().slideDown(300); + if($(this).hasClass("hit")) { + flag = !flag; + $(".sub").hide(); + $(".sub_bg").hide(); + } + + + console.log("메뉴IDX", headerIdx) + })//메뉴 호버 + + + } + + $(".gnb > ul > li").on("mouseleave", function(){ + $(".sub_bg").stop().slideUp(200); + $(".sub").hide(); + + console.log("메뉴IDX", headerIdx) + })//메뉴 호버 + + $(".lang").on("click", function(){ + $(this).find("ul").toggle(); + }) + + + + + + + + + $indicator.on("click", function(){ + nowIdx = $indicator.index($(this)); + + $(".service_container").stop().animate({"left" :-(nowIdx*1200)},400) + + $indicator.eq(nowIdx).addClass("on").siblings().removeClass("on"); + + })//service에 indicator 클릭시 fnc + + // $(".service_1 > ul > li").on("click", function(){ + // console.log("test", $(".more > a").eq(nowIdx)) + // nowIdx = $(".service_1 > ul > li").index($(this)); + // $(".more > a").eq(nowIdx); + // }) + + + + + + // $(".service_container li").on({ + // "mouseenter" : function(){ + // $(this).find(".topic").css({"color" : "#333"}) + // $(this).find(".info").css({"opacity" : 1}) + // }, + // "mouseleave" : function(){ + // $(this).find(".topic").css({"color" : "#fff"}) + // $(this).find(".info").css({"opacity" : 0}) + // } + // }) + + + + + +})//핸들러1 + +$(function(){ + $(".toggle").on("click", function(){ + + $(this).toggleClass("clse"); + $(".gnb").toggle(); + })//토글 버튼 클릭이벤트 +}) + +$(function(){ + var nowIdx = 0; + + $(".prev").on("click", function(){ + if(nowIdx == 0) { + nowIdx = $(".service_1 > ul > li").length-1; + }else { + nowIdx--; + } + $(".service_container").stop().animate({"left" : -(nowIdx*350)},300) + console.log("prev", nowIdx) + + }) + + $(".next").on("click", function(){ + if(nowIdx == $(".service_1 > ul > li").length-1) { + nowIdx = 0; + }else { + nowIdx++; + + } + $(".service_container").stop().animate({"left" : -(nowIdx*350)},300) + console.log("prev", nowIdx) + + }) +}) + +/*연구과제*/ +$(function() { + var $sch_bar = $(".schedule_content ul"); + var $strength_top_li = $(".strength_top ul li "); + var $strength_bot_li = $(".strength_bot ul li "); + var $bg = $(".rnd_outside > ol > li > dl"); + var nowIdx = 0; + var hitIdx = 0; + + + $sch_bar.on("mouseover", function() { + $(this).find(".sch_info").css({"color" : "#fff", "background-color" : "#1e3571"}) + $(this).find(".sch_info > em").css({"color" : "#fff", "opacity" : 1}) + }) + $sch_bar.on("mouseout", function() { + $(this).find(".sch_info").css({"color" : "#000", "background-color" : "inherit"}) + }) + + + $strength_top_li.on("mouseover", function() { + $(this).find(".line").stop().animate({"width" : 70},100); + $(this).find(".strength_info").css({"color" : "#000"}) + }) + $strength_top_li.on("mouseout", function() { + $(this).find(".line").stop().animate({"width" : 0},400) + $(this).find(".strength_info").css({"color" : "#d1d1d1"}) + }) + $strength_bot_li.on("mouseover", function() { + $(this).find(".line").stop().animate({"width" : 70},100); + $(this).find(".strength_info").css({"color" : "#000"}) + }) + $strength_bot_li.on("mouseout", function() { + $(this).find(".line").stop().animate({"width" : 0},400) + $(this).find(".strength_info").css({"color" : "#d1d1d1"}) + }) + + + + $(".rnd_outside > ol > li").on("mouseover", function() { + nowIdx = $(".rnd_outside > ol > li").index($(this)); + $(".rnd_outside > ol > li > dl").eq(nowIdx).stop().animate({"opacity" : 1},300); + } ) + + $(".rnd_outside > ol > li").on("mouseout", function() { + nowIdx = $(".rnd_outside > ol > li").index($(this)); + $(".rnd_outside > ol > li > dl").stop().animate({"opacity" : 0},300); + } ) +}) diff --git a/eng/js/function.js.bak b/eng/js/function.js.bak new file mode 100644 index 0000000..58c9318 --- /dev/null +++ b/eng/js/function.js.bak @@ -0,0 +1,324 @@ +$(function(){ + //console.log("hi") + var $mainMnu = $(".gnb > ul > li"); + + var $mVisual = $("#mVisual"); + var $mVisual_img = $("#mVisual").find(".mVisual_img > ul > li"); + var $mVisual_txt = $("#mVisual").find(".mVisual_txt > ul > li"); + + var $mVisual_indicator = $(".mVisual_indicator"); + var $mVisual_prev_btn = $mVisual_indicator.find(".mVisual_prev_btn"); + var $mVisual_next_btn = $mVisual_indicator.find(".mVisual_next_btn"); + + var $indicator = $(".service_indicator > ul > li"); + var $service_li = $(".service_container > div > ul > li"); + + var nowIdx = 0; + var oldIdx = nowIdx; + var headerIdx = 0; + var sectionTop = []; + + $(".section").each(function(idx){ + sectionTop[idx] = $(this).offset().top; + console.log("section", sectionTop[idx]) + }); //section의 높이값 알아내기 + + + + + + + + function nextIdx() { + if(nowIdx ==$mVisual_img.size()-1) { + nowIdx = 0; + }else { + nowIdx++; + } + }//nextIdx + + function nextFnc() { + $mVisual_img.eq(nowIdx).stop().fadeIn(400); + $mVisual_img.eq(oldIdx).stop().fadeOut(400); + $mVisual_txt.eq(nowIdx).stop().fadeIn(400); + $mVisual_txt.eq(oldIdx).stop().fadeOut(400); + + + oldIdx = nowIdx; + }//nextFnc + + function start() { + myInterval = setInterval(function(){ + nextIdx(); + nextFnc(); + },4500) + }//interval start + + function restart() { + clearInterval(myInterval) + setTimeout(function(){ + start(); + },1) + }//clearInterval and start + + + //$mVisual.height($(window).height()); + $(document).ready(function(){ + $mainMnu.find("a").eq(nowIdx).addClass("on"); + start(); + $mVisual_img.hide().eq(nowIdx).show(); + $mVisual_txt.hide().eq(nowIdx).show(); + // $("html, body").stop().animate({"scrollTop" : 0},400) + })//새로고침시 상단으로 이동 + + $(window).on("load resize", function(){ + $mVisual.height($(window).height()); + + })// window load , resize fnc + + + $(window).on("resize", function(){ + if($(window).width()<769 && $(window).width()>767) { + location.reload(); + console.log("reload") + } + })//반응형 넘어갈때 양옆 +-1로 새로고침 + + + $(window).on("load", function(){ + //$(".gnb").css({"display" : "block"}) + //$("html, body").stop().animate({"scrollTop" : 0},400) + + $indicator.eq(nowIdx).addClass("on"); + + + + $(".mVisual_indicator").on({ + "mouseover" : function(){ + clearInterval(myInterval); + $(".mVisual_txt").stop().css({"background-color" : "rgba(0,0,0,0.8)"}) + }, + "mouseleave" : function(){ + $(".mVisual_txt").stop().css({"background-color" : "rgba(0,0,0,0.6)"}) + start(); + } + }) + })// window load fnc + + $mVisual_prev_btn.on("click", function(){ + + + restart(); + + if(nowIdx == 0) { + nowIdx = $mVisual_img.size()-1; + }else { + nowIdx--; + } + + $mVisual_img.eq(nowIdx).stop().fadeIn(400); + $mVisual_img.eq(oldIdx).stop().fadeOut(400); + + $mVisual_txt.eq(nowIdx).stop().fadeIn(400); + $mVisual_txt.eq(oldIdx).stop().fadeOut(400); + + oldIdx = nowIdx; + + })//end of $mVisual_prev_btn click + + $mVisual_next_btn.on("click", function(){ + + //restart(); + nextIdx(); + nextFnc(); + + })//end of $mVisual_next_btn click + + + + + $(window).on("scroll", function(){ + + var scrollH = $(window).scrollTop(); + + if($(window).width()>768) { + if(scrollH >100) { + $(".upArrow").stop().fadeIn(400) + $("header").css({"background-color" : "#1e3571"}) + }else { + $(".upArrow").stop().fadeOut(400) + $("header").css({"background-color" : "rgba(000,000,000,0.3)"}) + }//위로 올라가기 나타남과 없어짐 + }else if($(window).width()<768) { + if(scrollH >100) { + $(".upArrow").stop().fadeIn(400) + $("header").css({"background-color" : "#1e3571"}) + }else { + $(".upArrow").stop().fadeOut(400) + $("header").css({"background-color" : "#444"}) + }//위로 올라가기 나타남과 없어짐 + } + + // if(scrollH >sectionTop[1]-200) { + // $("header").css({"background" : "#2381e3"}) //rgba(000,000,000,0.5) + // }else { + // $("header").css({"background" : "none"}) + // } + + + + $mVisual.css({"opacity" : 1-(scrollH/900)}) + + for(i=0; i<5; i++) { + if(scrollH >= sectionTop[i]-320) { + $(".gnb > ul > li").eq(i).children().addClass("on").parent().siblings().children().removeClass("on"); + } + } + + + })// upArrow 나타내기 + + $(".upArrow").on("click", function(){ + $("html, body").stop().animate({"scrollTop" : 0},400) + })//올라가기 위로 + + $(".downArrow").on("click", function(){ + $("html, body").stop().animate({"scrollTop" : sectionTop[1]-70},600) + })//home에서 아래 화살표 클릭시 이동 + + + + + + $("header").find(".headerM").on("click", function(){ + headerIdx = $(".headerM").index($(this)); + $("html, body").stop().animate({"scrollTop" : sectionTop[headerIdx]-70},600) + console.log("sectionTop", headerIdx) + //e.preventDefault(); + });//메인메뉴 클릭시 해당 section이동 + + +var flag = false; + + if($(window).width()>768) { + $(".gnb > ul > li").on("mouseover", function(){ + !flag; + headerIdx = $(".headerM").index($(this)); + $(".sub_bg").stop().slideDown(200); + $(".sub").eq(headerIdx-1).stop().slideDown(100); + if($(this).hasClass("hit")) { + flag = !flag; + $(".sub").hide(); + $(".sub_bg").stop().slideUp(100); + } + + + console.log("PC") + })//메뉴 호버 + }else { + $(".gnb > ul > li").on("click", function(){ + !flag; + headerIdx = $(".headerM").index($(this)); + //$(".sub_bg").stop().slideDown(200); + $(".sub").eq(headerIdx-1).stop().slideDown(300); + if($(this).hasClass("hit")) { + flag = !flag; + $(".sub").hide(); + $(".sub_bg").hide(); + } + + + console.log("메뉴IDX", headerIdx) + })//메뉴 호버 + + + } + + $(".gnb > ul > li").on("mouseleave", function(){ + $(".sub_bg").stop().slideUp(200); + $(".sub").hide(); + + console.log("메뉴IDX", headerIdx) + })//메뉴 호버 + + $(".lang").on("click", function(){ + $(this).find("ul").toggle(); + }) + + + + + + + + + $indicator.on("click", function(){ + nowIdx = $indicator.index($(this)); + + $(".service_container").stop().animate({"left" :-(nowIdx*1200)},400) + + $indicator.eq(nowIdx).addClass("on").siblings().removeClass("on"); + + })//service에 indicator 클릭시 fnc + + // $(".service_1 > ul > li").on("click", function(){ + // console.log("test", $(".more > a").eq(nowIdx)) + // nowIdx = $(".service_1 > ul > li").index($(this)); + // $(".more > a").eq(nowIdx); + // }) + + + + + + // $(".service_container li").on({ + // "mouseenter" : function(){ + // $(this).find(".topic").css({"color" : "#333"}) + // $(this).find(".info").css({"opacity" : 1}) + // }, + // "mouseleave" : function(){ + // $(this).find(".topic").css({"color" : "#fff"}) + // $(this).find(".info").css({"opacity" : 0}) + // } + // }) + + + + + +})//핸들러1 + +$(function(){ + $(".toggle").on("click", function(){ + + $(this).toggleClass("clse"); + $(".gnb").toggle(); + })//토글 버튼 클릭이벤트 +}) + +$(function(){ + var nowIdx = 0; + + $(".prev").on("click", function(){ + if(nowIdx == 0) { + nowIdx = $(".service_1 > ul > li").length-1; + }else { + nowIdx--; + } + $(".service_container").stop().animate({"left" : -(nowIdx*350)},300) + console.log("prev", nowIdx) + + }) + + $(".next").on("click", function(){ + if(nowIdx == $(".service_1 > ul > li").length-1) { + nowIdx = 0; + }else { + nowIdx++; + + } + $(".service_container").stop().animate({"left" : -(nowIdx*350)},300) + console.log("prev", nowIdx) + + }) +}) diff --git a/eng/js/move.js b/eng/js/move.js new file mode 100644 index 0000000..31d7793 --- /dev/null +++ b/eng/js/move.js @@ -0,0 +1,32 @@ +$(function(){ + $(window).on("load", function(){ + $(".topic_bg_info > ul").stop().animate({"padding-top" : "220px","opacity" : "1"},700) + $(".topic2_bg > ul").stop().animate({"padding-top" : "220px","opacity" : "1"},700) + $(".topic3_bg > ul").stop().animate({"padding-top" : "220px","opacity" : "1"},700) + })// + + var nowIdx = 0; + var busArr=[]; + + $(".bs_section").each(function(idx){ + busArr[idx] = $(this).offset().top; + console.log("높이값", busArr[idx]) + })//사업영역의 해당 div의 높이값 구하기 + + + + + + $(".category > ul > li").on("click", function(){ + nowIdx = $(".category > ul > li").index($(this)); + + $(".category > ul > li").eq(nowIdx).addClass("on").siblings().removeClass("on"); + $("html, body").stop().animate({"scrollTop" : busArr[nowIdx]-22},400) + + })//클릭시 색변경 및 이동 + + + + + +}) diff --git a/eng/js/si.js b/eng/js/si.js new file mode 100644 index 0000000..cdc4387 --- /dev/null +++ b/eng/js/si.js @@ -0,0 +1,15 @@ +$(function(){ + + $(window).on("load", function(){ + var nowIdx = 3; + var busArr=[]; + + $(".bs_section").each(function(idx){ + busArr[idx] = $(this).offset().top; + console.log("높이값", busArr[idx]) + })//사업영역의 해당 div의 높이값 구하기 + + $("html, body").stop().animate({"scrollTop" : busArr[nowIdx]-22},400) + }) + +}) diff --git a/eng/js/soc.js b/eng/js/soc.js new file mode 100644 index 0000000..ea83a01 --- /dev/null +++ b/eng/js/soc.js @@ -0,0 +1,15 @@ +$(function(){ + + $(window).on("load", function(){ + var nowIdx = 2; + var busArr=[]; + + $(".bs_section").each(function(idx){ + busArr[idx] = $(this).offset().top; + console.log("높이값", busArr[idx]) + })//사업영역의 해당 div의 높이값 구하기 + + $("html, body").stop().animate({"scrollTop" : busArr[nowIdx]-22},400) + }) + +}) diff --git a/eng/js/sub_fnc.js b/eng/js/sub_fnc.js new file mode 100644 index 0000000..734e937 --- /dev/null +++ b/eng/js/sub_fnc.js @@ -0,0 +1,48 @@ +$(function(){ + var headerIdx = 0; + + $(".downArrow").on("click", function(){ + $("html, body").stop().animate({"scrollTop" : sectionTop[1]-70},600) + })//home에서 아래 화살표 클릭시 이동 + + + + $(window).on("scroll", function(){ + + var scrollH = $(window).scrollTop(); + + if($(window).width()>768) { + if(scrollH >100) { + $(".upArrow").stop().fadeIn(400) + $("header").css({"background-color" : "#1e3571"}) + }else { + $(".upArrow").stop().fadeOut(400) + $("header").css({"background-color" : "rgba(000,000,000,0.3)"}) + }//위로 올라가기 나타남과 없어짐 + }else if($(window).width()<768) { + if(scrollH >100) { + $(".upArrow").stop().fadeIn(400) + $("header").css({"background-color" : "#1e3571"}) + }else { + $(".upArrow").stop().fadeOut(400) + $("header").css({"background-color" : "#444"}) + }//위로 올라가기 나타남과 없어짐 + } + + // if(scrollH >sectionTop[1]-200) { + // $("header").css({"background" : "#2381e3"}) //rgba(000,000,000,0.5) + // }else { + // $("header").css({"background" : "none"}) + // } + + + + + + + })// upArrow 나타내기 + + $(".upArrow").on("click", function(){ + $("html, body").stop().animate({"scrollTop" : 0},400) + })//올라가기 위로 +}) diff --git a/eng/sitemap.html b/eng/sitemap.html new file mode 100644 index 0000000..28ef013 --- /dev/null +++ b/eng/sitemap.html @@ -0,0 +1,79 @@ + + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • COMPANY
    • +
    • -
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 SITEMAP +
    +
    + +
    + + + \ No newline at end of file diff --git a/images/BULE.png b/images/BULE.png new file mode 100644 index 0000000..c80a028 Binary files /dev/null and b/images/BULE.png differ diff --git a/images/RND.jpg b/images/RND.jpg new file mode 100644 index 0000000..123899a Binary files /dev/null and b/images/RND.jpg differ diff --git a/images/RND_b.jpg b/images/RND_b.jpg new file mode 100644 index 0000000..70ec775 Binary files /dev/null and b/images/RND_b.jpg differ diff --git a/images/RND_m.png b/images/RND_m.png new file mode 100644 index 0000000..1af9319 Binary files /dev/null and b/images/RND_m.png differ diff --git a/images/Untitled-2.png b/images/Untitled-2.png new file mode 100644 index 0000000..4026f44 Binary files /dev/null and b/images/Untitled-2.png differ diff --git a/images/accident._111.jpg b/images/accident._111.jpg new file mode 100644 index 0000000..acd815a Binary files /dev/null and b/images/accident._111.jpg differ diff --git a/images/accident.jpg b/images/accident.jpg new file mode 100644 index 0000000..a47b807 Binary files /dev/null and b/images/accident.jpg differ diff --git a/images/accident2.jpg b/images/accident2.jpg new file mode 100644 index 0000000..030ac2a Binary files /dev/null and b/images/accident2.jpg differ diff --git a/images/ai.jpg b/images/ai.jpg new file mode 100644 index 0000000..5edbf69 Binary files /dev/null and b/images/ai.jpg differ diff --git a/images/ai.png b/images/ai.png new file mode 100644 index 0000000..809e8b7 Binary files /dev/null and b/images/ai.png differ diff --git a/images/ai_2.png b/images/ai_2.png new file mode 100644 index 0000000..02ccb61 Binary files /dev/null and b/images/ai_2.png differ diff --git a/images/ai_c.png b/images/ai_c.png new file mode 100644 index 0000000..7523aaf Binary files /dev/null and b/images/ai_c.png differ diff --git a/images/anchor.png b/images/anchor.png new file mode 100644 index 0000000..4a7a1e9 Binary files /dev/null and b/images/anchor.png differ diff --git a/images/asd.jpg b/images/asd.jpg new file mode 100644 index 0000000..20853bf Binary files /dev/null and b/images/asd.jpg differ diff --git a/images/asd_01.jpg b/images/asd_01.jpg new file mode 100644 index 0000000..2c3d048 Binary files /dev/null and b/images/asd_01.jpg differ diff --git a/images/banner_01.png b/images/banner_01.png new file mode 100644 index 0000000..897b9fa Binary files /dev/null and b/images/banner_01.png differ diff --git a/images/brain.png b/images/brain.png new file mode 100644 index 0000000..dd14c40 Binary files /dev/null and b/images/brain.png differ diff --git a/images/brain_hover.png b/images/brain_hover.png new file mode 100644 index 0000000..40958eb Binary files /dev/null and b/images/brain_hover.png differ diff --git a/images/btn_main01.jpg b/images/btn_main01.jpg new file mode 100644 index 0000000..2ef60e8 Binary files /dev/null and b/images/btn_main01.jpg differ diff --git a/images/busi.jpg b/images/busi.jpg new file mode 100644 index 0000000..08e2fa1 Binary files /dev/null and b/images/busi.jpg differ diff --git a/images/busi_2.jpg b/images/busi_2.jpg new file mode 100644 index 0000000..6717da1 Binary files /dev/null and b/images/busi_2.jpg differ diff --git a/images/busi_2_b.png b/images/busi_2_b.png new file mode 100644 index 0000000..cf0ce63 Binary files /dev/null and b/images/busi_2_b.png differ diff --git a/images/busi_2_bb.jpg b/images/busi_2_bb.jpg new file mode 100644 index 0000000..523f114 Binary files /dev/null and b/images/busi_2_bb.jpg differ diff --git a/images/call.png b/images/call.png new file mode 100644 index 0000000..942ca8e Binary files /dev/null and b/images/call.png differ diff --git a/images/car1.jpg b/images/car1.jpg new file mode 100644 index 0000000..2d4dfea Binary files /dev/null and b/images/car1.jpg differ diff --git a/images/car1_w.jpg b/images/car1_w.jpg new file mode 100644 index 0000000..1ec1545 Binary files /dev/null and b/images/car1_w.jpg differ diff --git a/images/car2.jpg b/images/car2.jpg new file mode 100644 index 0000000..a0e3158 Binary files /dev/null and b/images/car2.jpg differ diff --git a/images/car2.png b/images/car2.png new file mode 100644 index 0000000..5152e4d Binary files /dev/null and b/images/car2.png differ diff --git a/images/certificate_01.png b/images/certificate_01.png new file mode 100644 index 0000000..5007110 Binary files /dev/null and b/images/certificate_01.png differ diff --git a/images/certificate_02.png b/images/certificate_02.png new file mode 100644 index 0000000..4d941ee Binary files /dev/null and b/images/certificate_02.png differ diff --git a/images/certificate_03.png b/images/certificate_03.png new file mode 100644 index 0000000..5e059ed Binary files /dev/null and b/images/certificate_03.png differ diff --git a/images/certificate_04.png b/images/certificate_04.png new file mode 100644 index 0000000..a1dd0ca Binary files /dev/null and b/images/certificate_04.png differ diff --git a/images/certificate_05.png b/images/certificate_05.png new file mode 100644 index 0000000..5e86c5a Binary files /dev/null and b/images/certificate_05.png differ diff --git a/images/certificate_06.png b/images/certificate_06.png new file mode 100644 index 0000000..ec6a6c0 Binary files /dev/null and b/images/certificate_06.png differ diff --git a/images/certificate_07.png b/images/certificate_07.png new file mode 100644 index 0000000..022f834 Binary files /dev/null and b/images/certificate_07.png differ diff --git a/images/certificate_08.png b/images/certificate_08.png new file mode 100644 index 0000000..d908d7d Binary files /dev/null and b/images/certificate_08.png differ diff --git a/images/certificate_09.png b/images/certificate_09.png new file mode 100644 index 0000000..e31d076 Binary files /dev/null and b/images/certificate_09.png differ diff --git a/images/certificate_10.png b/images/certificate_10.png new file mode 100644 index 0000000..b4ef453 Binary files /dev/null and b/images/certificate_10.png differ diff --git a/images/certificate_11.png b/images/certificate_11.png new file mode 100644 index 0000000..572dbcd Binary files /dev/null and b/images/certificate_11.png differ diff --git a/images/certificate_12.png b/images/certificate_12.png new file mode 100644 index 0000000..5222cf6 Binary files /dev/null and b/images/certificate_12.png differ diff --git a/images/certificate_13.png b/images/certificate_13.png new file mode 100644 index 0000000..fc190de Binary files /dev/null and b/images/certificate_13.png differ diff --git a/images/cla_new.png b/images/cla_new.png new file mode 100644 index 0000000..261fdcc Binary files /dev/null and b/images/cla_new.png differ diff --git a/images/classi.jpg b/images/classi.jpg new file mode 100644 index 0000000..68a63c7 Binary files /dev/null and b/images/classi.jpg differ diff --git a/images/classification.jpg b/images/classification.jpg new file mode 100644 index 0000000..2453f5e Binary files /dev/null and b/images/classification.jpg differ diff --git a/images/classification.png b/images/classification.png new file mode 100644 index 0000000..859c701 Binary files /dev/null and b/images/classification.png differ diff --git a/images/classification_1.png b/images/classification_1.png new file mode 100644 index 0000000..ff178d6 Binary files /dev/null and b/images/classification_1.png differ diff --git a/images/classification_2.png b/images/classification_2.png new file mode 100644 index 0000000..9fec634 Binary files /dev/null and b/images/classification_2.png differ diff --git a/images/clock.png b/images/clock.png new file mode 100644 index 0000000..693e124 Binary files /dev/null and b/images/clock.png differ diff --git a/images/cod.png b/images/cod.png new file mode 100644 index 0000000..cf75a76 Binary files /dev/null and b/images/cod.png differ diff --git a/images/coding.png b/images/coding.png new file mode 100644 index 0000000..fc3d563 Binary files /dev/null and b/images/coding.png differ diff --git a/images/coding_c.png b/images/coding_c.png new file mode 100644 index 0000000..1c350e3 Binary files /dev/null and b/images/coding_c.png differ diff --git a/images/company.jpg b/images/company.jpg new file mode 100644 index 0000000..cfe50c4 Binary files /dev/null and b/images/company.jpg differ diff --git a/images/company_01.jpg b/images/company_01.jpg new file mode 100644 index 0000000..078c723 Binary files /dev/null and b/images/company_01.jpg differ diff --git a/images/company_02.jpg b/images/company_02.jpg new file mode 100644 index 0000000..9572831 Binary files /dev/null and b/images/company_02.jpg differ diff --git a/images/company_03.jpg b/images/company_03.jpg new file mode 100644 index 0000000..66facda Binary files /dev/null and b/images/company_03.jpg differ diff --git a/images/company_04.png b/images/company_04.png new file mode 100644 index 0000000..609755e Binary files /dev/null and b/images/company_04.png differ diff --git a/images/company_04_bg.png b/images/company_04_bg.png new file mode 100644 index 0000000..a424aef Binary files /dev/null and b/images/company_04_bg.png differ diff --git a/images/company_04_click.png b/images/company_04_click.png new file mode 100644 index 0000000..85f345d Binary files /dev/null and b/images/company_04_click.png differ diff --git a/images/company_b.jpg b/images/company_b.jpg new file mode 100644 index 0000000..16dce65 Binary files /dev/null and b/images/company_b.jpg differ diff --git a/images/company_work.png b/images/company_work.png new file mode 100644 index 0000000..0f9501d Binary files /dev/null and b/images/company_work.png differ diff --git a/images/contact_1.jpg b/images/contact_1.jpg new file mode 100644 index 0000000..a2da5d3 Binary files /dev/null and b/images/contact_1.jpg differ diff --git a/images/contact_b.jpg b/images/contact_b.jpg new file mode 100644 index 0000000..150cd3c Binary files /dev/null and b/images/contact_b.jpg differ diff --git a/images/contact_logo.png b/images/contact_logo.png new file mode 100644 index 0000000..f46b33b Binary files /dev/null and b/images/contact_logo.png differ diff --git a/images/contect.jpg b/images/contect.jpg new file mode 100644 index 0000000..fa342e0 Binary files /dev/null and b/images/contect.jpg differ diff --git a/images/dbnt.jpg b/images/dbnt.jpg new file mode 100644 index 0000000..b703051 Binary files /dev/null and b/images/dbnt.jpg differ diff --git a/images/dbnt_m.png b/images/dbnt_m.png new file mode 100644 index 0000000..027aa7c Binary files /dev/null and b/images/dbnt_m.png differ diff --git a/images/dbnt_text.jpg b/images/dbnt_text.jpg new file mode 100644 index 0000000..c7a3075 Binary files /dev/null and b/images/dbnt_text.jpg differ diff --git a/images/dbnt_text.png b/images/dbnt_text.png new file mode 100644 index 0000000..bd94972 Binary files /dev/null and b/images/dbnt_text.png differ diff --git a/images/dbnt_text_e.jpg b/images/dbnt_text_e.jpg new file mode 100644 index 0000000..7a1bf28 Binary files /dev/null and b/images/dbnt_text_e.jpg differ diff --git a/images/dbnt_text_e.png b/images/dbnt_text_e.png new file mode 100644 index 0000000..e582269 Binary files /dev/null and b/images/dbnt_text_e.png differ diff --git a/images/disaster.jpg b/images/disaster.jpg new file mode 100644 index 0000000..515cd57 Binary files /dev/null and b/images/disaster.jpg differ diff --git a/images/disaster_w.jpg b/images/disaster_w.jpg new file mode 100644 index 0000000..8419686 Binary files /dev/null and b/images/disaster_w.jpg differ diff --git a/images/dot_2.PNG b/images/dot_2.PNG new file mode 100644 index 0000000..34cb92c Binary files /dev/null and b/images/dot_2.PNG differ diff --git a/images/dot_3.PNG b/images/dot_3.PNG new file mode 100644 index 0000000..1784f9f Binary files /dev/null and b/images/dot_3.PNG differ diff --git a/images/dot_l.png b/images/dot_l.png new file mode 100644 index 0000000..7ee6760 Binary files /dev/null and b/images/dot_l.png differ diff --git a/images/dot_r.png b/images/dot_r.png new file mode 100644 index 0000000..8a01192 Binary files /dev/null and b/images/dot_r.png differ diff --git a/images/education.png b/images/education.png new file mode 100644 index 0000000..add5491 Binary files /dev/null and b/images/education.png differ diff --git a/images/eee.jpg b/images/eee.jpg new file mode 100644 index 0000000..15e06a5 Binary files /dev/null and b/images/eee.jpg differ diff --git a/images/email_ico.png b/images/email_ico.png new file mode 100644 index 0000000..9423c5a Binary files /dev/null and b/images/email_ico.png differ diff --git a/images/favicon.ico b/images/favicon.ico new file mode 100644 index 0000000..d08d184 Binary files /dev/null and b/images/favicon.ico differ diff --git a/images/footer_ico/youtube.png b/images/footer_ico/youtube.png new file mode 100644 index 0000000..9fcbe8b Binary files /dev/null and b/images/footer_ico/youtube.png differ diff --git a/images/footer_ico/youtube_white.png b/images/footer_ico/youtube_white.png new file mode 100644 index 0000000..7db16d8 Binary files /dev/null and b/images/footer_ico/youtube_white.png differ diff --git a/images/help.png b/images/help.png new file mode 100644 index 0000000..e680f55 Binary files /dev/null and b/images/help.png differ diff --git a/images/img_00033_dem.jpg b/images/img_00033_dem.jpg new file mode 100644 index 0000000..c16c217 Binary files /dev/null and b/images/img_00033_dem.jpg differ diff --git a/images/korearoad.png b/images/korearoad.png new file mode 100644 index 0000000..47f3599 Binary files /dev/null and b/images/korearoad.png differ diff --git a/images/korearoad_1.png b/images/korearoad_1.png new file mode 100644 index 0000000..faa4354 Binary files /dev/null and b/images/korearoad_1.png differ diff --git a/images/korearoad_2.png b/images/korearoad_2.png new file mode 100644 index 0000000..cf4202b Binary files /dev/null and b/images/korearoad_2.png differ diff --git a/images/korearoad_3.png b/images/korearoad_3.png new file mode 100644 index 0000000..1723e07 Binary files /dev/null and b/images/korearoad_3.png differ diff --git a/images/korearoad_4.png b/images/korearoad_4.png new file mode 100644 index 0000000..d1b8ae2 Binary files /dev/null and b/images/korearoad_4.png differ diff --git a/images/logo.png b/images/logo.png new file mode 100644 index 0000000..c80a028 Binary files /dev/null and b/images/logo.png differ diff --git a/images/logo_w.png b/images/logo_w.png new file mode 100644 index 0000000..b63be90 Binary files /dev/null and b/images/logo_w.png differ diff --git a/images/lunar/Ori_00033_ori.jpg b/images/lunar/Ori_00033_ori.jpg new file mode 100644 index 0000000..3c42348 Binary files /dev/null and b/images/lunar/Ori_00033_ori.jpg differ diff --git a/images/lunar/img_00033.jpg b/images/lunar/img_00033.jpg new file mode 100644 index 0000000..6c374c3 Binary files /dev/null and b/images/lunar/img_00033.jpg differ diff --git a/images/lunar/img_00033_dem.jpg b/images/lunar/img_00033_dem.jpg new file mode 100644 index 0000000..c16c217 Binary files /dev/null and b/images/lunar/img_00033_dem.jpg differ diff --git a/images/lunar/img_00033_shd.jpg b/images/lunar/img_00033_shd.jpg new file mode 100644 index 0000000..b6d9b3c Binary files /dev/null and b/images/lunar/img_00033_shd.jpg differ diff --git a/images/m_R.jpg b/images/m_R.jpg new file mode 100644 index 0000000..abf7e55 Binary files /dev/null and b/images/m_R.jpg differ diff --git a/images/main_rnd.png b/images/main_rnd.png new file mode 100644 index 0000000..de3daf1 Binary files /dev/null and b/images/main_rnd.png differ diff --git a/images/map.png b/images/map.png new file mode 100644 index 0000000..520f9a5 Binary files /dev/null and b/images/map.png differ diff --git a/images/map_2.png b/images/map_2.png new file mode 100644 index 0000000..6e5d685 Binary files /dev/null and b/images/map_2.png differ diff --git a/images/message.png b/images/message.png new file mode 100644 index 0000000..aeb96a2 Binary files /dev/null and b/images/message.png differ diff --git a/images/module.jpg b/images/module.jpg new file mode 100644 index 0000000..49b3d52 Binary files /dev/null and b/images/module.jpg differ diff --git a/images/module_1.jpg b/images/module_1.jpg new file mode 100644 index 0000000..18b2582 Binary files /dev/null and b/images/module_1.jpg differ diff --git a/images/module_2.jpg b/images/module_2.jpg new file mode 100644 index 0000000..b9d188f Binary files /dev/null and b/images/module_2.jpg differ diff --git a/images/module_3.jpg b/images/module_3.jpg new file mode 100644 index 0000000..cd336c0 Binary files /dev/null and b/images/module_3.jpg differ diff --git a/images/money.png b/images/money.png new file mode 100644 index 0000000..27efebf Binary files /dev/null and b/images/money.png differ diff --git a/images/moon.jpg b/images/moon.jpg new file mode 100644 index 0000000..2f0c6b5 Binary files /dev/null and b/images/moon.jpg differ diff --git a/images/moon_w.jpg b/images/moon_w.jpg new file mode 100644 index 0000000..a133d43 Binary files /dev/null and b/images/moon_w.jpg differ diff --git a/images/mvisual_01.jpg b/images/mvisual_01.jpg new file mode 100644 index 0000000..802f738 Binary files /dev/null and b/images/mvisual_01.jpg differ diff --git a/images/mvisual_02.jpg b/images/mvisual_02.jpg new file mode 100644 index 0000000..0a4ee04 Binary files /dev/null and b/images/mvisual_02.jpg differ diff --git a/images/network.png b/images/network.png new file mode 100644 index 0000000..357a186 Binary files /dev/null and b/images/network.png differ diff --git a/images/one.jpg b/images/one.jpg new file mode 100644 index 0000000..932d7d6 Binary files /dev/null and b/images/one.jpg differ diff --git a/images/organigation.jpg b/images/organigation.jpg new file mode 100644 index 0000000..231e2c1 Binary files /dev/null and b/images/organigation.jpg differ diff --git a/images/organigation_2.jpg b/images/organigation_2.jpg new file mode 100644 index 0000000..dd2cb00 Binary files /dev/null and b/images/organigation_2.jpg differ diff --git a/images/organigation_eng.jpg b/images/organigation_eng.jpg new file mode 100644 index 0000000..ef7788c Binary files /dev/null and b/images/organigation_eng.jpg differ diff --git a/images/organization.jpg b/images/organization.jpg new file mode 100644 index 0000000..899a530 Binary files /dev/null and b/images/organization.jpg differ diff --git a/images/parst.png b/images/parst.png new file mode 100644 index 0000000..b532b77 Binary files /dev/null and b/images/parst.png differ diff --git a/images/pop.png b/images/pop.png new file mode 100644 index 0000000..572bb78 Binary files /dev/null and b/images/pop.png differ diff --git a/images/print_ico.png b/images/print_ico.png new file mode 100644 index 0000000..a8ecc75 Binary files /dev/null and b/images/print_ico.png differ diff --git a/images/reference/deep/1.PNG b/images/reference/deep/1.PNG new file mode 100644 index 0000000..83300c7 Binary files /dev/null and b/images/reference/deep/1.PNG differ diff --git a/images/reference/deep/2.PNG b/images/reference/deep/2.PNG new file mode 100644 index 0000000..a2a2601 Binary files /dev/null and b/images/reference/deep/2.PNG differ diff --git a/images/reference/deep/3.PNG b/images/reference/deep/3.PNG new file mode 100644 index 0000000..e66162f Binary files /dev/null and b/images/reference/deep/3.PNG differ diff --git a/images/reference/deep/4.PNG b/images/reference/deep/4.PNG new file mode 100644 index 0000000..d283daf Binary files /dev/null and b/images/reference/deep/4.PNG differ diff --git a/images/reference/deep/one.PNG b/images/reference/deep/one.PNG new file mode 100644 index 0000000..bd9a50a Binary files /dev/null and b/images/reference/deep/one.PNG differ diff --git a/images/reference/deep/two.PNG b/images/reference/deep/two.PNG new file mode 100644 index 0000000..15392a5 Binary files /dev/null and b/images/reference/deep/two.PNG differ diff --git a/images/reference/korea/1.PNG b/images/reference/korea/1.PNG new file mode 100644 index 0000000..9433cd5 Binary files /dev/null and b/images/reference/korea/1.PNG differ diff --git a/images/reference/korea/2.PNG b/images/reference/korea/2.PNG new file mode 100644 index 0000000..0fdf352 Binary files /dev/null and b/images/reference/korea/2.PNG differ diff --git a/images/reference/korea/3.PNG b/images/reference/korea/3.PNG new file mode 100644 index 0000000..4fde139 Binary files /dev/null and b/images/reference/korea/3.PNG differ diff --git a/images/reference/korea/4.PNG b/images/reference/korea/4.PNG new file mode 100644 index 0000000..4937ccf Binary files /dev/null and b/images/reference/korea/4.PNG differ diff --git a/images/reference/korea/5.PNG b/images/reference/korea/5.PNG new file mode 100644 index 0000000..0b01a98 Binary files /dev/null and b/images/reference/korea/5.PNG differ diff --git a/images/reference/lunar/1.PNG b/images/reference/lunar/1.PNG new file mode 100644 index 0000000..9155326 Binary files /dev/null and b/images/reference/lunar/1.PNG differ diff --git a/images/reference/lunar/2.PNG b/images/reference/lunar/2.PNG new file mode 100644 index 0000000..23c4a71 Binary files /dev/null and b/images/reference/lunar/2.PNG differ diff --git a/images/reference/lunar/3.PNG b/images/reference/lunar/3.PNG new file mode 100644 index 0000000..d18e27f Binary files /dev/null and b/images/reference/lunar/3.PNG differ diff --git a/images/reference/lunar/4.PNG b/images/reference/lunar/4.PNG new file mode 100644 index 0000000..5b7bd80 Binary files /dev/null and b/images/reference/lunar/4.PNG differ diff --git a/images/reference/lunar/5.PNG b/images/reference/lunar/5.PNG new file mode 100644 index 0000000..bb168c3 Binary files /dev/null and b/images/reference/lunar/5.PNG differ diff --git a/images/reference/module/1.PNG b/images/reference/module/1.PNG new file mode 100644 index 0000000..1739b65 Binary files /dev/null and b/images/reference/module/1.PNG differ diff --git a/images/reference/module/2.PNG b/images/reference/module/2.PNG new file mode 100644 index 0000000..32c93b7 Binary files /dev/null and b/images/reference/module/2.PNG differ diff --git a/images/reference/module/3.PNG b/images/reference/module/3.PNG new file mode 100644 index 0000000..96e28bf Binary files /dev/null and b/images/reference/module/3.PNG differ diff --git a/images/road.jpg b/images/road.jpg new file mode 100644 index 0000000..4a48519 Binary files /dev/null and b/images/road.jpg differ diff --git a/images/road_w.jpg b/images/road_w.jpg new file mode 100644 index 0000000..950b302 Binary files /dev/null and b/images/road_w.jpg differ diff --git a/images/server.jpg b/images/server.jpg new file mode 100644 index 0000000..b9a8dd0 Binary files /dev/null and b/images/server.jpg differ diff --git a/images/server_2.jpg b/images/server_2.jpg new file mode 100644 index 0000000..a52bd06 Binary files /dev/null and b/images/server_2.jpg differ diff --git a/images/server_3.jpg b/images/server_3.jpg new file mode 100644 index 0000000..02396eb Binary files /dev/null and b/images/server_3.jpg differ diff --git a/images/si.jpg b/images/si.jpg new file mode 100644 index 0000000..8294ad2 Binary files /dev/null and b/images/si.jpg differ diff --git a/images/smart.jpg b/images/smart.jpg new file mode 100644 index 0000000..44272cf Binary files /dev/null and b/images/smart.jpg differ diff --git a/images/smart_b.jpg b/images/smart_b.jpg new file mode 100644 index 0000000..7e9af87 Binary files /dev/null and b/images/smart_b.jpg differ diff --git a/images/soc_c.png b/images/soc_c.png new file mode 100644 index 0000000..d59b336 Binary files /dev/null and b/images/soc_c.png differ diff --git a/images/support.png b/images/support.png new file mode 100644 index 0000000..e753cf4 Binary files /dev/null and b/images/support.png differ diff --git a/images/tel_ico.png b/images/tel_ico.png new file mode 100644 index 0000000..ef6c3e3 Binary files /dev/null and b/images/tel_ico.png differ diff --git a/images/toggle.png b/images/toggle.png new file mode 100644 index 0000000..a2f5f50 Binary files /dev/null and b/images/toggle.png differ diff --git a/images/toggle_cls.png b/images/toggle_cls.png new file mode 100644 index 0000000..aee07c7 Binary files /dev/null and b/images/toggle_cls.png differ diff --git a/images/tt.jpg b/images/tt.jpg new file mode 100644 index 0000000..a05ffb9 Binary files /dev/null and b/images/tt.jpg differ diff --git a/images/video_img_01.png b/images/video_img_01.png new file mode 100644 index 0000000..d7f978e Binary files /dev/null and b/images/video_img_01.png differ diff --git a/images/video_img_02.png b/images/video_img_02.png new file mode 100644 index 0000000..01b8d75 Binary files /dev/null and b/images/video_img_02.png differ diff --git a/images/video_img_03.png b/images/video_img_03.png new file mode 100644 index 0000000..adce1f9 Binary files /dev/null and b/images/video_img_03.png differ diff --git a/images/video_img_04.png b/images/video_img_04.png new file mode 100644 index 0000000..cfdd93c Binary files /dev/null and b/images/video_img_04.png differ diff --git a/images/www.jpg b/images/www.jpg new file mode 100644 index 0000000..03234dc Binary files /dev/null and b/images/www.jpg differ diff --git a/images/zoom.png b/images/zoom.png new file mode 100644 index 0000000..e62461b Binary files /dev/null and b/images/zoom.png differ diff --git a/images/zoom_1.png b/images/zoom_1.png new file mode 100644 index 0000000..6303944 Binary files /dev/null and b/images/zoom_1.png differ diff --git a/images/zoom_g.png b/images/zoom_g.png new file mode 100644 index 0000000..9540e9e Binary files /dev/null and b/images/zoom_g.png differ diff --git a/images/zoom_w.png b/images/zoom_w.png new file mode 100644 index 0000000..9782d88 Binary files /dev/null and b/images/zoom_w.png differ diff --git a/inc/footer.php b/inc/footer.php new file mode 100644 index 0000000..543965e --- /dev/null +++ b/inc/footer.php @@ -0,0 +1,88 @@ + +
    diff --git a/inc/footer_eng.php b/inc/footer_eng.php new file mode 100644 index 0000000..ad14015 --- /dev/null +++ b/inc/footer_eng.php @@ -0,0 +1,80 @@ + +
    \ No newline at end of file diff --git a/inc/menubar.php b/inc/menubar.php new file mode 100644 index 0000000..7da13e7 --- /dev/null +++ b/inc/menubar.php @@ -0,0 +1,68 @@ + + +
    + + diff --git a/inc/menubar_eng.php b/inc/menubar_eng.php new file mode 100644 index 0000000..55063cf --- /dev/null +++ b/inc/menubar_eng.php @@ -0,0 +1,58 @@ + + +
    + diff --git a/inc/pageheader.php b/inc/pageheader.php new file mode 100644 index 0000000..1010487 --- /dev/null +++ b/inc/pageheader.php @@ -0,0 +1,13 @@ + + + + + + + 디비엔텍 + + + + + + \ No newline at end of file diff --git a/inc/pageheader_eng.php b/inc/pageheader_eng.php new file mode 100644 index 0000000..96e5c6b --- /dev/null +++ b/inc/pageheader_eng.php @@ -0,0 +1,14 @@ + + + + + + + DBNtech + + + + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..24b273f --- /dev/null +++ b/index.html @@ -0,0 +1,104 @@ + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • +
      +
      DETECTION
      +
      다양한 객체 검출 모델을 적용하여 영상 내에 분포된 객체들을 찾아 실시간으로 경계박스를 생성하고 검출된 객체가 무엇인지 식별
      + +
      +
    • +
    • +
      +
      TRACKING
      +
      Detection 단계에서 얻은 위치 정보를 통해 특정 객체의 위치 변화를 추적
      + + +
      +
    • +
    • +
      +
      주식회사 디비엔텍
      + +
      +
    • +
    +
    +
    +
    + + + +
    + + + + + diff --git a/js/jobsFnc.js b/js/jobsFnc.js new file mode 100644 index 0000000..010e38d --- /dev/null +++ b/js/jobsFnc.js @@ -0,0 +1,59 @@ +$(function(){ + //console.log("gd") + + var target = $(".jobsContainer ul"); + + const pt1 = ["개발/연구원", "개발/프로그래머"]; + const pt2 = ["연구개발부", "시스템개발부"]; +/* + $(window).on("load", function(){ + $(".jobsOverView").hide(); + }) +*/ + + + target.on("click", function(){ + var nowIdx = $(this).index(); + + $(".jobsOverView>ul").hide().eq(nowIdx).fadeIn(400); + + + + $(".jobsOverView").fadeIn(400); + + $("html, body").css({ + overflow: "hidden", + }) + + }) +/* + $(".jobsOverView").on("click", function(){ + $(this).fadeOut(400) + $("html, body").css({ + overflow: "auto", + }) + }) +*/ + $(".close").on("click", function(){ + $(".jobsOverView").fadeOut(400) + $("html, body").css({ + overflow: "auto", + }) + }) + + $(document).keyup(function(e) { + + if ( e.keyCode == 27) { + + $(".jobsOverView").fadeOut(400) + $("html, body").css({ + overflow: "auto", + }) + + } + + }) + + + +}) \ No newline at end of file diff --git a/js/mainfnc.js b/js/mainfnc.js new file mode 100644 index 0000000..bd5ef1c --- /dev/null +++ b/js/mainfnc.js @@ -0,0 +1,308 @@ +$(function(){ + $close = $(".popup"); + + $close.on("click",function(){ + $(this).fadeOut(200); + }) +}) + +$(function() { + var ww = $(window).width(); + var flag = 0; + //console.log("ww",ww) + + if (ww < 769) { + flag = 1 + + $("nav .inner>ul>li>a").on("click", function(){ + var nowIdx = $(this).parent().index(); + console.log("nowIDx",nowIdx) + + if(nowIdx > 2) { + return true; + }else { + return false; + } + + + }) + } +})// 모바일일때 a태그 활성화 비활성화 + + +$(function(){ + var $banner = $(".mainBannerCont").find("ul"); + var nowIdx = 0; + var oldIdx = nowIdx; + var myInterval = null; + + var ww = $(window).width(); + + $(window).on("load", function(){ + $banner.children().hide().eq(nowIdx).show(); + start(); + + if (ww >768) { + $banner.find("dl").css({ + "padding":"110px 0" + }) + }else { + $banner.find("dl").css({ + "padding":"150px 0" + }) + } + + + + }) + + function nextFnc(){ + //var nowIdx = $banner.children().index(); + + if(nowIdx > $banner.children().length-2) { + nowIdx = 0; + }else { + nowIdx++; + } + + if(ww>768) { + $banner.children().eq(oldIdx).stop().fadeOut(400).find("dl").animate({ + "padding":" 0" + }); + $banner.children().eq(nowIdx).stop().fadeIn(400).find("dl").animate({ + "padding":"110px 0" + }); + }else { + $banner.children().eq(oldIdx).stop().fadeOut(400).find("dl").animate({ + "padding":" 0" + }); + $banner.children().eq(nowIdx).stop().fadeIn(400).find("dl").animate({ + "padding":"150px 0" + }); + } + + + + oldIdx = nowIdx; + + //console.log("old",oldIdx) + //console.log("nowIdx",nowIdx) + + } + + + function start() { + setInterval(function(){ + nextFnc() + },6500)//5000 + } + + })//메인 슬라이드 + + + +$(function(){ +/* + $(window).on("load", function(){ + $("p").css({ + "opacity":"0" + }).stop().fadeIn(300) + $(".mainIndustries ul").css({ + "opacity":"0" + }) + }) +*/ +$menu = $("nav").find(".inner ul li ul"); + +if ($(window).width() > 768) { + $("nav ul").on("mouseenter", function() { + $(".subMenuBg").stop().slideDown(200, function(){ + $menu.css({ + "display" :"block" + }) + }); + }) + + $("nav").on("mouseleave", function() { + //console.log("out") + + $menu.stop().slideUp(100, function(){ + $(".subMenuBg").stop().slideUp(100) + }); + }) + + //navgation func + + $menu.on("mouseenter", function(){ + $(this).children().css({ + //"background": "#fff", + }) + }) + + $menu.on("mouseleave", function(){ + $(this).css({ + //"background": "none" + }) + }) + + + + + +}// if + + + + var ww = $(window).width(); + + if(ww > 768) { + $("nav .inner>ul> li").on("mouseenter", function(){ + $(this).prepend( + '

    ' + ).find(".point").animate({ + "width" : "85%", + },200) + }) + }else { + $("nav .inner>ul> li").on("mouseenter", function(){ + $(this).prepend( + '

    ' + ).find(".point").animate({ + "width" : "100%", + },200) + }) + } + $menu.parent().on("mouseleave", function(){ + $(".point").remove(); + }) + + + +})//nav + + +$(function(){ + $btnMobile = $(".mobileToggle"); + $navigation = $("nav ul"); + $subNavi = $navigation.find("li ul li"); + + if ($(window).width() < 769) { + + + $btnMobile.on("click", function(){ + + $(this).toggleClass("toggleActive"); + + $navigation.toggle(); + + }) + + $navigation.find("li a").on("click", function(){ + var nowIdx = $(this).parent().index(); + + $navigation.children().eq(nowIdx).find("li").toggleClass("toggleActiveSub"); + + + }) + + } + +}) + + + +$(function(){ + + + $(".mainIndustries ul").children().on("mouseenter", function(){ + var nowIdx = $(this).index(); + //console.log(nowIdx) + + $(this).find(".inbg").css({ + "background-image": "url(../images/zoom_w.png)", + "background-repeat": "no-repeat", + "background-position": "50% 50%", + "background-color": "rgba(000,000,000,0.6)", + "background-size" : "20%" + }) + }) + + $(".mainIndustries ul").children().on("mouseout", function(){ + var nowIdx = $(this).index(); + //console.log(nowIdx) + + + $(this).find(".inbg").css({ + "background-image": "none", + "background-repeat": "no-repeat", + "background-position": "50% 50%", + "background-color": "rgba(255,255,255,0.0)" + }) + }) + + + +})//메인 비즈니스 + + + +$(function(){ + + var infoBtn = $(".info_table").find("li:nth-child(1) dl dd"); + var infoTable = $(".info_table").find("li:nth-child(2) dl dd"); + var nowIdx = 0; + var oldIdx = nowIdx; + + + var ww = $(window).width() + //console.log(ww) + if(ww<769) { + $(window).on("load", function(){ + var nowIdx = infoTable.index() + //console.log(nowIdx) + infoTable.hide().eq(nowIdx).show(); + }) + } + + + + //console.log(nowIdx) + $(".infoBtn").find("li:last-child").on("click", function(){ + + var nowIdx = infoTable.index(); + + + infoTable.eq(oldIdx).fadeIn(400); + infoTable.eq(nowIdx).fadeOut(400); + + + + + + oldIdx = nowIdx; + + })//right + + + + + + + + + + +})//company01 페이드 슬라이드 + + + + +$(function(){ + + var ww =$(window).width() + + if(ww<769) { + //$(".info_table").hide() + $(".swiperWrap").show() + } +}) \ No newline at end of file diff --git a/js/picLoad.js b/js/picLoad.js new file mode 100644 index 0000000..debaebc --- /dev/null +++ b/js/picLoad.js @@ -0,0 +1,16 @@ +$(function(){ + //console.log("connect") + + var picList = [""]; + + $(".test").append(picList).css({ + "background-size" : "cover" + + }) + + + + + + +}) \ No newline at end of file diff --git a/js/rnd.js b/js/rnd.js new file mode 100644 index 0000000..5857b40 --- /dev/null +++ b/js/rnd.js @@ -0,0 +1,182 @@ +$(function(){ + $(".btn_fix").on("click", function(){ + //console.log("log") + + $(this).parent().toggleClass("active_fixBtn"); + $(this).toggleClass("trn_anc"); + + }) +})// RND 페이지 고정 네비 기능******************************** + +$(function(){ + // { + // var big1 = $(".bigPic1>iframe") + // var small = $(".deepLearning").find("ul>li:last-child>dl>dd:last-child>ul>li"); + // var list_1 = ['https://www.youtube.com/embed/8WVW2Di2Vu4', + // 'https://www.youtube.com/embed/DFCG6hxfiQ4', + // 'https://www.youtube.com/embed/vuAcFXQRxoQ', + // ]; + // small.on("click", function(){ + // var nowIdx1 = $(this).index() + // big1.attr('src', list_1[nowIdx1]); + // $(this).css({ + // "border":"3px solid orange", + // "transition":"0.2s" + // }).siblings().css({ + // "border":"0px solid orange", + // "transition":"0.1s" + // }) + // }) + // }//deep Fnc + { + var big1 = $(".bigPic1>img") + var small = $(".deepLearning").find("ul>li:last-child>dl>dd:last-child>ul>li"); + var list_1 = ['../images/video_img_01.png', + '../images/video_img_02.png', + '../images/video_img_04.png', + ]; + small.on("click", function(){ + var nowIdx1 = $(this).index() + big1.attr('src', list_1[nowIdx1]); + $(this).css({ + "border":"3px solid orange", + "transition":"0.2s" + }).siblings().css({ + "border":"0px solid orange", + "transition":"0.1s" + }) + }) + }//deep Fnc + + + { + var big2 = $(".bigPic2>img") + var small = $(".lunarSystem").find("ul>li:last-child>dl>dd:last-child>ul>li"); + var list_2 = ['../images/lunar/Ori_00033_ori.jpg', + '../images/lunar/img_00033_dem.jpg', + '../images/lunar/img_00033.jpg', + ]; + small.on("click", function(){ + var nowIdx2 = $(this).index() + big2.attr('src', list_2[nowIdx2]); + $(this).css({ + "border":"3px solid orange", + "transition":"0.2s" + }).siblings().css({ + "border":"0px solid orange", + "transition":"0.1s" + }) + }) + }//lunar Fnc + + { + + var big3 = $(".bigPic3>img") + var small = $(".LiquefactionModule").find("ul>li:last-child>dl>dd:last-child>ul>li"); + var list_3 = ['../images/module_1.jpg', + '../images/module_2.jpg', + '../images/module_3.jpg', + ]; + small.on("click", function(){ + var nowIdx3 = $(this).index() + big3.attr('src', list_3[nowIdx3]); + $(this).css({ + "border":"3px solid orange", + "transition":"0.2s" + }).siblings().css({ + "border":"0px solid orange", + "transition":"0.1s" + }) + }) + }//module_ Fnc + + + { + var big4 = $(".bigPic4>img") + var small = $(".koreaRoadSign").find("ul>li:last-child>dl>dd:last-child>ul>li"); + var list_4 = ['../images/korearoad_1.png', + '../images/korearoad_2.png', + '../images/korearoad_3.png', + ]; + small.on("click", function(){ + var nowIdx4 = $(this).index() + big4.attr('src', list_4[nowIdx4]); + $(this).css({ + "border":"3px solid orange", + "transition":"0.2s" + }).siblings().css({ + "border":"0px solid orange", + "transition":"0.1s" + }) + }) + }//koreaRoadSign Fnc + +})//RND 이미지 변환****************************************** + + + + + +/* +$(function(){ + + + //var height = $(this).scrollTop(); + var deep = $(".deepLearning").offset().top;//요소의 맨 위 값 + var deepH = $(window).height(); + + var lunar = $(".lunarSystem").offset().top;//요소의 맨 위 값 + var lunarH = $(window).height(); + var module_ = $(".LiquefactionModule").offset().top;//요소의 맨 위 값 + var moduleH = $(window).height(); + var road = $(".koreaRoadSign").offset().top;//요소의 맨 위 값 + var roadH = $(window).height(); + + //console.log(deepH) + + var ww = $(window).width(); + if(ww>768) { + $(window).on("load", function(){ + $(".deepLearning").height(deepH); + $(".lunarSystem").height(lunarH); + $(".LiquefactionModule").height(moduleH); + $(".koreaRoadSign").height(roadH); + }) + } + + + $(".fixMenu").find("li:nth-child(1)").on("click", function(e){ + $(window).scrollTop(deep); + + e.preventDefault(); + })//딥러닝 + + $(".fixMenu").find("li:nth-child(2)").on("click", function(e){ + $(window).scrollTop(lunar+90); + + e.preventDefault(); + })//달과제 + + $(".fixMenu").find("li:nth-child(3)").on("click", function(e){ + $(window).scrollTop(module_ + 220); + + e.preventDefault(); + })//액상화 + + $(".fixMenu").find("li:nth-child(4)").on("click", function(e){ + var road = $(".koreaRoadSign").offset().top;//요소의 맨 위 값 + $(window).scrollTop(road); + + e.preventDefault(); + })//도로표지 + + + $("nav ul>li:nth-child(3)>ul>li>a").on("click", function(){ + //alert("hit") + + }) + + + +}) +*/ diff --git a/js/rnd_scroll.js b/js/rnd_scroll.js new file mode 100644 index 0000000..763e3af --- /dev/null +++ b/js/rnd_scroll.js @@ -0,0 +1,13 @@ +$(function(){ + var scrollTopDeep = $(".deepLearning").offset().top; + var scrollToplunar = $(".lunarSystem").offset().top; + var scrollTopModule = $(".LiquefactionModule").offset().top; + var scrollTopkorea = $(".koreaRoadSign").offset().top; + + $(window).on("load", function(){ + $(document).scroll(function(){ + + }) + }) + +}) \ No newline at end of file diff --git a/js/swiper.min.js b/js/swiper.min.js new file mode 100644 index 0000000..0dbcde4 --- /dev/null +++ b/js/swiper.min.js @@ -0,0 +1,19 @@ +/** + * Swiper 3.4.2 + * Most modern mobile touch slider and framework with hardware accelerated transitions + * + * http://www.idangero.us/swiper/ + * + * Copyright 2017, Vladimir Kharlampidi + * The iDangero.us + * http://www.idangero.us/ + * + * Licensed under MIT + * + * Released on: March 10, 2017 + */ +!function(){"use strict";var e,a=function(s,i){function r(e){return Math.floor(e)}function n(){var e=T.params.autoplay,a=T.slides.eq(T.activeIndex);a.attr("data-swiper-autoplay")&&(e=a.attr("data-swiper-autoplay")||T.params.autoplay),T.autoplayTimeoutId=setTimeout(function(){T.params.loop?(T.fixLoop(),T._slideNext(),T.emit("onAutoplay",T)):T.isEnd?i.autoplayStopOnLast?T.stopAutoplay():(T._slideTo(0),T.emit("onAutoplay",T)):(T._slideNext(),T.emit("onAutoplay",T))},e)}function o(a,t){var s=e(a.target);if(!s.is(t))if("string"==typeof t)s=s.parents(t);else if(t.nodeType){var i;return s.parents().each(function(e,a){a===t&&(i=t)}),i?t:void 0}if(0!==s.length)return s[0]}function l(e,a){a=a||{};var t=window.MutationObserver||window.WebkitMutationObserver,s=new t(function(e){e.forEach(function(e){T.onResize(!0),T.emit("onObserverUpdate",T,e)})});s.observe(e,{attributes:void 0===a.attributes||a.attributes,childList:void 0===a.childList||a.childList,characterData:void 0===a.characterData||a.characterData}),T.observers.push(s)}function p(e){e.originalEvent&&(e=e.originalEvent);var a=e.keyCode||e.charCode;if(!T.params.allowSwipeToNext&&(T.isHorizontal()&&39===a||!T.isHorizontal()&&40===a))return!1;if(!T.params.allowSwipeToPrev&&(T.isHorizontal()&&37===a||!T.isHorizontal()&&38===a))return!1;if(!(e.shiftKey||e.altKey||e.ctrlKey||e.metaKey||document.activeElement&&document.activeElement.nodeName&&("input"===document.activeElement.nodeName.toLowerCase()||"textarea"===document.activeElement.nodeName.toLowerCase()))){if(37===a||39===a||38===a||40===a){var t=!1;if(T.container.parents("."+T.params.slideClass).length>0&&0===T.container.parents("."+T.params.slideActiveClass).length)return;var s={left:window.pageXOffset,top:window.pageYOffset},i=window.innerWidth,r=window.innerHeight,n=T.container.offset();T.rtl&&(n.left=n.left-T.container[0].scrollLeft);for(var o=[[n.left,n.top],[n.left+T.width,n.top],[n.left,n.top+T.height],[n.left+T.width,n.top+T.height]],l=0;l=s.left&&p[0]<=s.left+i&&p[1]>=s.top&&p[1]<=s.top+r&&(t=!0)}if(!t)return}T.isHorizontal()?(37!==a&&39!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),(39===a&&!T.rtl||37===a&&T.rtl)&&T.slideNext(),(37===a&&!T.rtl||39===a&&T.rtl)&&T.slidePrev()):(38!==a&&40!==a||(e.preventDefault?e.preventDefault():e.returnValue=!1),40===a&&T.slideNext(),38===a&&T.slidePrev()),T.emit("onKeyPress",T,a)}}function d(e){var a=0,t=0,s=0,i=0;return"detail"in e&&(t=e.detail),"wheelDelta"in e&&(t=-e.wheelDelta/120),"wheelDeltaY"in e&&(t=-e.wheelDeltaY/120),"wheelDeltaX"in e&&(a=-e.wheelDeltaX/120),"axis"in e&&e.axis===e.HORIZONTAL_AXIS&&(a=t,t=0),s=10*a,i=10*t,"deltaY"in e&&(i=e.deltaY),"deltaX"in e&&(s=e.deltaX),(s||i)&&e.deltaMode&&(1===e.deltaMode?(s*=40,i*=40):(s*=800,i*=800)),s&&!a&&(a=s<1?-1:1),i&&!t&&(t=i<1?-1:1),{spinX:a,spinY:t,pixelX:s,pixelY:i}}function u(e){e.originalEvent&&(e=e.originalEvent);var a=0,t=T.rtl?-1:1,s=d(e);if(T.params.mousewheelForceToAxis)if(T.isHorizontal()){if(!(Math.abs(s.pixelX)>Math.abs(s.pixelY)))return;a=s.pixelX*t}else{if(!(Math.abs(s.pixelY)>Math.abs(s.pixelX)))return;a=s.pixelY}else a=Math.abs(s.pixelX)>Math.abs(s.pixelY)?-s.pixelX*t:-s.pixelY;if(0!==a){if(T.params.mousewheelInvert&&(a=-a),T.params.freeMode){var i=T.getWrapperTranslate()+a*T.params.mousewheelSensitivity,r=T.isBeginning,n=T.isEnd;if(i>=T.minTranslate()&&(i=T.minTranslate()),i<=T.maxTranslate()&&(i=T.maxTranslate()),T.setWrapperTransition(0),T.setWrapperTranslate(i),T.updateProgress(),T.updateActiveIndex(),(!r&&T.isBeginning||!n&&T.isEnd)&&T.updateClasses(),T.params.freeModeSticky?(clearTimeout(T.mousewheel.timeout),T.mousewheel.timeout=setTimeout(function(){T.slideReset()},300)):T.params.lazyLoading&&T.lazy&&T.lazy.load(),T.emit("onScroll",T,e),T.params.autoplay&&T.params.autoplayDisableOnInteraction&&T.stopAutoplay(),0===i||i===T.maxTranslate())return}else{if((new window.Date).getTime()-T.mousewheel.lastScrollTime>60)if(a<0)if(T.isEnd&&!T.params.loop||T.animating){if(T.params.mousewheelReleaseOnEdges)return!0}else T.slideNext(),T.emit("onScroll",T,e);else if(T.isBeginning&&!T.params.loop||T.animating){if(T.params.mousewheelReleaseOnEdges)return!0}else T.slidePrev(),T.emit("onScroll",T,e);T.mousewheel.lastScrollTime=(new window.Date).getTime()}return e.preventDefault?e.preventDefault():e.returnValue=!1,!1}}function c(a,t){a=e(a);var s,i,r,n=T.rtl?-1:1;s=a.attr("data-swiper-parallax")||"0",i=a.attr("data-swiper-parallax-x"),r=a.attr("data-swiper-parallax-y"),i||r?(i=i||"0",r=r||"0"):T.isHorizontal()?(i=s,r="0"):(r=s,i="0"),i=i.indexOf("%")>=0?parseInt(i,10)*t*n+"%":i*t*n+"px",r=r.indexOf("%")>=0?parseInt(r,10)*t+"%":r*t+"px",a.transform("translate3d("+i+", "+r+",0px)")}function m(e){return 0!==e.indexOf("on")&&(e=e[0]!==e[0].toUpperCase()?"on"+e[0].toUpperCase()+e.substring(1):"on"+e),e}if(!(this instanceof a))return new a(s,i);var h={direction:"horizontal",touchEventsTarget:"container",initialSlide:0,speed:300,autoplay:!1,autoplayDisableOnInteraction:!0,autoplayStopOnLast:!1,iOSEdgeSwipeDetection:!1,iOSEdgeSwipeThreshold:20,freeMode:!1,freeModeMomentum:!0,freeModeMomentumRatio:1,freeModeMomentumBounce:!0,freeModeMomentumBounceRatio:1,freeModeMomentumVelocityRatio:1,freeModeSticky:!1,freeModeMinimumVelocity:.02,autoHeight:!1,setWrapperSize:!1,virtualTranslate:!1,effect:"slide",coverflow:{rotate:50,stretch:0,depth:100,modifier:1,slideShadows:!0},flip:{slideShadows:!0,limitRotation:!0},cube:{slideShadows:!0,shadow:!0,shadowOffset:20,shadowScale:.94},fade:{crossFade:!1},parallax:!1,zoom:!1,zoomMax:3,zoomMin:1,zoomToggle:!0,scrollbar:null,scrollbarHide:!0,scrollbarDraggable:!1,scrollbarSnapOnRelease:!1,keyboardControl:!1,mousewheelControl:!1,mousewheelReleaseOnEdges:!1,mousewheelInvert:!1,mousewheelForceToAxis:!1,mousewheelSensitivity:1,mousewheelEventsTarged:"container",hashnav:!1,hashnavWatchState:!1,history:!1,replaceState:!1,breakpoints:void 0,spaceBetween:0,slidesPerView:1,slidesPerColumn:1,slidesPerColumnFill:"column",slidesPerGroup:1,centeredSlides:!1,slidesOffsetBefore:0,slidesOffsetAfter:0,roundLengths:!1,touchRatio:1,touchAngle:45,simulateTouch:!0,shortSwipes:!0,longSwipes:!0,longSwipesRatio:.5,longSwipesMs:300,followFinger:!0,onlyExternal:!1,threshold:0,touchMoveStopPropagation:!0,touchReleaseOnEdges:!1,uniqueNavElements:!0,pagination:null,paginationElement:"span",paginationClickable:!1,paginationHide:!1,paginationBulletRender:null,paginationProgressRender:null,paginationFractionRender:null,paginationCustomRender:null,paginationType:"bullets",resistance:!0,resistanceRatio:.85,nextButton:null,prevButton:null,watchSlidesProgress:!1,watchSlidesVisibility:!1,grabCursor:!1,preventClicks:!0,preventClicksPropagation:!0,slideToClickedSlide:!1,lazyLoading:!1,lazyLoadingInPrevNext:!1,lazyLoadingInPrevNextAmount:1,lazyLoadingOnTransitionStart:!1,preloadImages:!0,updateOnImagesReady:!0,loop:!1,loopAdditionalSlides:0,loopedSlides:null,control:void 0,controlInverse:!1,controlBy:"slide",normalizeSlideIndex:!0,allowSwipeToPrev:!0,allowSwipeToNext:!0,swipeHandler:null,noSwiping:!0,noSwipingClass:"swiper-no-swiping",passiveListeners:!0,containerModifierClass:"swiper-container-",slideClass:"swiper-slide",slideActiveClass:"swiper-slide-active",slideDuplicateActiveClass:"swiper-slide-duplicate-active",slideVisibleClass:"swiper-slide-visible",slideDuplicateClass:"swiper-slide-duplicate",slideNextClass:"swiper-slide-next",slideDuplicateNextClass:"swiper-slide-duplicate-next",slidePrevClass:"swiper-slide-prev",slideDuplicatePrevClass:"swiper-slide-duplicate-prev",wrapperClass:"swiper-wrapper",bulletClass:"swiper-pagination-bullet",bulletActiveClass:"swiper-pagination-bullet-active",buttonDisabledClass:"swiper-button-disabled",paginationCurrentClass:"swiper-pagination-current",paginationTotalClass:"swiper-pagination-total",paginationHiddenClass:"swiper-pagination-hidden",paginationProgressbarClass:"swiper-pagination-progressbar",paginationClickableClass:"swiper-pagination-clickable",paginationModifierClass:"swiper-pagination-",lazyLoadingClass:"swiper-lazy",lazyStatusLoadingClass:"swiper-lazy-loading",lazyStatusLoadedClass:"swiper-lazy-loaded",lazyPreloaderClass:"swiper-lazy-preloader",notificationClass:"swiper-notification",preloaderClass:"preloader",zoomContainerClass:"swiper-zoom-container",observer:!1,observeParents:!1,a11y:!1,prevSlideMessage:"Previous slide",nextSlideMessage:"Next slide",firstSlideMessage:"This is the first slide",lastSlideMessage:"This is the last slide",paginationBulletMessage:"Go to slide {{index}}",runCallbacksOnInit:!0},g=i&&i.virtualTranslate;i=i||{};var f={};for(var v in i)if("object"!=typeof i[v]||null===i[v]||(i[v].nodeType||i[v]===window||i[v]===document||void 0!==t&&i[v]instanceof t||"undefined"!=typeof jQuery&&i[v]instanceof jQuery))f[v]=i[v];else{f[v]={};for(var w in i[v])f[v][w]=i[v][w]}for(var y in h)if(void 0===i[y])i[y]=h[y];else if("object"==typeof i[y])for(var x in h[y])void 0===i[y][x]&&(i[y][x]=h[y][x]);var T=this;if(T.params=i,T.originalParams=f,T.classNames=[],void 0!==e&&void 0!==t&&(e=t),(void 0!==e||(e=void 0===t?window.Dom7||window.Zepto||window.jQuery:t))&&(T.$=e,T.currentBreakpoint=void 0,T.getActiveBreakpoint=function(){if(!T.params.breakpoints)return!1;var e,a=!1,t=[];for(e in T.params.breakpoints)T.params.breakpoints.hasOwnProperty(e)&&t.push(e);t.sort(function(e,a){return parseInt(e,10)>parseInt(a,10)});for(var s=0;s=window.innerWidth&&!a&&(a=e);return a||"max"},T.setBreakpoint=function(){var e=T.getActiveBreakpoint();if(e&&T.currentBreakpoint!==e){var a=e in T.params.breakpoints?T.params.breakpoints[e]:T.originalParams,t=T.params.loop&&a.slidesPerView!==T.params.slidesPerView;for(var s in a)T.params[s]=a[s];T.currentBreakpoint=e,t&&T.destroyLoop&&T.reLoop(!0)}},T.params.breakpoints&&T.setBreakpoint(),T.container=e(s),0!==T.container.length)){if(T.container.length>1){var b=[];return T.container.each(function(){b.push(new a(this,i))}),b}T.container[0].swiper=T,T.container.data("swiper",T),T.classNames.push(T.params.containerModifierClass+T.params.direction),T.params.freeMode&&T.classNames.push(T.params.containerModifierClass+"free-mode"),T.support.flexbox||(T.classNames.push(T.params.containerModifierClass+"no-flexbox"),T.params.slidesPerColumn=1),T.params.autoHeight&&T.classNames.push(T.params.containerModifierClass+"autoheight"),(T.params.parallax||T.params.watchSlidesVisibility)&&(T.params.watchSlidesProgress=!0),T.params.touchReleaseOnEdges&&(T.params.resistanceRatio=0),["cube","coverflow","flip"].indexOf(T.params.effect)>=0&&(T.support.transforms3d?(T.params.watchSlidesProgress=!0,T.classNames.push(T.params.containerModifierClass+"3d")):T.params.effect="slide"),"slide"!==T.params.effect&&T.classNames.push(T.params.containerModifierClass+T.params.effect),"cube"===T.params.effect&&(T.params.resistanceRatio=0,T.params.slidesPerView=1,T.params.slidesPerColumn=1,T.params.slidesPerGroup=1,T.params.centeredSlides=!1,T.params.spaceBetween=0,T.params.virtualTranslate=!0),"fade"!==T.params.effect&&"flip"!==T.params.effect||(T.params.slidesPerView=1,T.params.slidesPerColumn=1,T.params.slidesPerGroup=1,T.params.watchSlidesProgress=!0,T.params.spaceBetween=0,void 0===g&&(T.params.virtualTranslate=!0)),T.params.grabCursor&&T.support.touch&&(T.params.grabCursor=!1),T.wrapper=T.container.children("."+T.params.wrapperClass),T.params.pagination&&(T.paginationContainer=e(T.params.pagination),T.params.uniqueNavElements&&"string"==typeof T.params.pagination&&T.paginationContainer.length>1&&1===T.container.find(T.params.pagination).length&&(T.paginationContainer=T.container.find(T.params.pagination)),"bullets"===T.params.paginationType&&T.params.paginationClickable?T.paginationContainer.addClass(T.params.paginationModifierClass+"clickable"):T.params.paginationClickable=!1,T.paginationContainer.addClass(T.params.paginationModifierClass+T.params.paginationType)),(T.params.nextButton||T.params.prevButton)&&(T.params.nextButton&&(T.nextButton=e(T.params.nextButton),T.params.uniqueNavElements&&"string"==typeof T.params.nextButton&&T.nextButton.length>1&&1===T.container.find(T.params.nextButton).length&&(T.nextButton=T.container.find(T.params.nextButton))),T.params.prevButton&&(T.prevButton=e(T.params.prevButton),T.params.uniqueNavElements&&"string"==typeof T.params.prevButton&&T.prevButton.length>1&&1===T.container.find(T.params.prevButton).length&&(T.prevButton=T.container.find(T.params.prevButton)))),T.isHorizontal=function(){return"horizontal"===T.params.direction},T.rtl=T.isHorizontal()&&("rtl"===T.container[0].dir.toLowerCase()||"rtl"===T.container.css("direction")),T.rtl&&T.classNames.push(T.params.containerModifierClass+"rtl"),T.rtl&&(T.wrongRTL="-webkit-box"===T.wrapper.css("display")),T.params.slidesPerColumn>1&&T.classNames.push(T.params.containerModifierClass+"multirow"),T.device.android&&T.classNames.push(T.params.containerModifierClass+"android"),T.container.addClass(T.classNames.join(" ")),T.translate=0,T.progress=0,T.velocity=0,T.lockSwipeToNext=function(){T.params.allowSwipeToNext=!1,T.params.allowSwipeToPrev===!1&&T.params.grabCursor&&T.unsetGrabCursor()},T.lockSwipeToPrev=function(){T.params.allowSwipeToPrev=!1,T.params.allowSwipeToNext===!1&&T.params.grabCursor&&T.unsetGrabCursor()},T.lockSwipes=function(){T.params.allowSwipeToNext=T.params.allowSwipeToPrev=!1,T.params.grabCursor&&T.unsetGrabCursor()},T.unlockSwipeToNext=function(){T.params.allowSwipeToNext=!0,T.params.allowSwipeToPrev===!0&&T.params.grabCursor&&T.setGrabCursor()},T.unlockSwipeToPrev=function(){T.params.allowSwipeToPrev=!0,T.params.allowSwipeToNext===!0&&T.params.grabCursor&&T.setGrabCursor()},T.unlockSwipes=function(){T.params.allowSwipeToNext=T.params.allowSwipeToPrev=!0,T.params.grabCursor&&T.setGrabCursor()},T.setGrabCursor=function(e){T.container[0].style.cursor="move",T.container[0].style.cursor=e?"-webkit-grabbing":"-webkit-grab",T.container[0].style.cursor=e?"-moz-grabbin":"-moz-grab",T.container[0].style.cursor=e?"grabbing":"grab"},T.unsetGrabCursor=function(){T.container[0].style.cursor=""},T.params.grabCursor&&T.setGrabCursor(),T.imagesToLoad=[],T.imagesLoaded=0,T.loadImage=function(e,a,t,s,i,r){function n(){r&&r()}var o;e.complete&&i?n():a?(o=new window.Image,o.onload=n,o.onerror=n,s&&(o.sizes=s),t&&(o.srcset=t),a&&(o.src=a)):n()},T.preloadImages=function(){function e(){void 0!==T&&null!==T&&T&&(void 0!==T.imagesLoaded&&T.imagesLoaded++,T.imagesLoaded===T.imagesToLoad.length&&(T.params.updateOnImagesReady&&T.update(),T.emit("onImagesReady",T)))}T.imagesToLoad=T.container.find("img");for(var a=0;a1)for(e=0;eT.slides.length)break;a.push(T.slides.eq(s)[0])}else a.push(T.slides.eq(T.activeIndex)[0]);for(e=0;et?i:t}t&&T.wrapper.css("height",t+"px")},T.updateContainerSize=function(){var e,a;e=void 0!==T.params.width?T.params.width:T.container[0].clientWidth,a=void 0!==T.params.height?T.params.height:T.container[0].clientHeight,0===e&&T.isHorizontal()||0===a&&!T.isHorizontal()||(e=e-parseInt(T.container.css("padding-left"),10)-parseInt(T.container.css("padding-right"),10),a=a-parseInt(T.container.css("padding-top"),10)-parseInt(T.container.css("padding-bottom"),10),T.width=e,T.height=a,T.size=T.isHorizontal()?T.width:T.height)},T.updateSlidesSize=function(){T.slides=T.wrapper.children("."+T.params.slideClass),T.snapGrid=[],T.slidesGrid=[],T.slidesSizesGrid=[];var e,a=T.params.spaceBetween,t=-T.params.slidesOffsetBefore,s=0,i=0;if(void 0!==T.size){"string"==typeof a&&a.indexOf("%")>=0&&(a=parseFloat(a.replace("%",""))/100*T.size),T.virtualSize=-a,T.rtl?T.slides.css({marginLeft:"",marginTop:""}):T.slides.css({marginRight:"",marginBottom:""});var n;T.params.slidesPerColumn>1&&(n=Math.floor(T.slides.length/T.params.slidesPerColumn)===T.slides.length/T.params.slidesPerColumn?T.slides.length:Math.ceil(T.slides.length/T.params.slidesPerColumn)*T.params.slidesPerColumn,"auto"!==T.params.slidesPerView&&"row"===T.params.slidesPerColumnFill&&(n=Math.max(n,T.params.slidesPerView*T.params.slidesPerColumn)));var o,l=T.params.slidesPerColumn,p=n/l,d=p-(T.params.slidesPerColumn*p-T.slides.length);for(e=0;e1){var c,m,h;"column"===T.params.slidesPerColumnFill?(m=Math.floor(e/l),h=e-m*l,(m>d||m===d&&h===l-1)&&++h>=l&&(h=0,m++),c=m+h*n/l,u.css({"-webkit-box-ordinal-group":c,"-moz-box-ordinal-group":c,"-ms-flex-order":c,"-webkit-order":c,order:c})):(h=Math.floor(e/p),m=e-h*p),u.css("margin-"+(T.isHorizontal()?"top":"left"),0!==h&&T.params.spaceBetween&&T.params.spaceBetween+"px").attr("data-swiper-column",m).attr("data-swiper-row",h)}"none"!==u.css("display")&&("auto"===T.params.slidesPerView?(o=T.isHorizontal()?u.outerWidth(!0):u.outerHeight(!0),T.params.roundLengths&&(o=r(o))):(o=(T.size-(T.params.slidesPerView-1)*a)/T.params.slidesPerView,T.params.roundLengths&&(o=r(o)),T.isHorizontal()?T.slides[e].style.width=o+"px":T.slides[e].style.height=o+"px"),T.slides[e].swiperSlideSize=o,T.slidesSizesGrid.push(o),T.params.centeredSlides?(t=t+o/2+s/2+a,0===s&&0!==e&&(t=t-T.size/2-a),0===e&&(t=t-T.size/2-a),Math.abs(t)<.001&&(t=0),i%T.params.slidesPerGroup==0&&T.snapGrid.push(t),T.slidesGrid.push(t)):(i%T.params.slidesPerGroup==0&&T.snapGrid.push(t),T.slidesGrid.push(t),t=t+o+a),T.virtualSize+=o+a,s=o,i++)}T.virtualSize=Math.max(T.virtualSize,T.size)+T.params.slidesOffsetAfter;var g;if(T.rtl&&T.wrongRTL&&("slide"===T.params.effect||"coverflow"===T.params.effect)&&T.wrapper.css({width:T.virtualSize+T.params.spaceBetween+"px"}),T.support.flexbox&&!T.params.setWrapperSize||(T.isHorizontal()?T.wrapper.css({width:T.virtualSize+T.params.spaceBetween+"px"}):T.wrapper.css({height:T.virtualSize+T.params.spaceBetween+"px"})),T.params.slidesPerColumn>1&&(T.virtualSize=(o+T.params.spaceBetween)*n,T.virtualSize=Math.ceil(T.virtualSize/T.params.slidesPerColumn)-T.params.spaceBetween,T.isHorizontal()?T.wrapper.css({width:T.virtualSize+T.params.spaceBetween+"px"}):T.wrapper.css({height:T.virtualSize+T.params.spaceBetween+"px"}),T.params.centeredSlides)){for(g=[],e=0;e1&&T.snapGrid.push(T.virtualSize-T.size)}0===T.snapGrid.length&&(T.snapGrid=[0]),0!==T.params.spaceBetween&&(T.isHorizontal()?T.rtl?T.slides.css({marginLeft:a+"px"}):T.slides.css({marginRight:a+"px"}):T.slides.css({marginBottom:a+"px"})),T.params.watchSlidesProgress&&T.updateSlidesOffset()}},T.updateSlidesOffset=function(){for(var e=0;eT.size&&(s=!0));for(a=T.activeIndex-1;a>=0;a--)T.slides[a]&&!s&&(i+=T.slides[a].swiperSlideSize,t++,i>T.size&&(s=!0))}else for(e=T.activeIndex+1;e=0&&r0&&n<=T.size||r<=0&&n>=T.size)&&T.slides.eq(t).addClass(T.params.slideVisibleClass)}s.progress=T.rtl?-i:i}}},T.updateProgress=function(e){void 0===e&&(e=T.translate||0);var a=T.maxTranslate()-T.minTranslate(),t=T.isBeginning,s=T.isEnd;0===a?(T.progress=0,T.isBeginning=T.isEnd=!0):(T.progress=(e-T.minTranslate())/a,T.isBeginning=T.progress<=0,T.isEnd=T.progress>=1),T.isBeginning&&!t&&T.emit("onReachBeginning",T),T.isEnd&&!s&&T.emit("onReachEnd",T),T.params.watchSlidesProgress&&T.updateSlidesProgress(e),T.emit("onProgress",T,T.progress)},T.updateActiveIndex=function(){var e,a,t,s=T.rtl?T.translate:-T.translate;for(a=0;a=T.slidesGrid[a]&&s=T.slidesGrid[a]&&s=T.slidesGrid[a]&&(e=a);T.params.normalizeSlideIndex&&(e<0||void 0===e)&&(e=0),t=Math.floor(e/T.params.slidesPerGroup),t>=T.snapGrid.length&&(t=T.snapGrid.length-1),e!==T.activeIndex&&(T.snapIndex=t,T.previousIndex=T.activeIndex,T.activeIndex=e,T.updateClasses(),T.updateRealIndex())},T.updateRealIndex=function(){T.realIndex=parseInt(T.slides.eq(T.activeIndex).attr("data-swiper-slide-index")||T.activeIndex,10)},T.updateClasses=function(){T.slides.removeClass(T.params.slideActiveClass+" "+T.params.slideNextClass+" "+T.params.slidePrevClass+" "+T.params.slideDuplicateActiveClass+" "+T.params.slideDuplicateNextClass+" "+T.params.slideDuplicatePrevClass);var a=T.slides.eq(T.activeIndex);a.addClass(T.params.slideActiveClass),i.loop&&(a.hasClass(T.params.slideDuplicateClass)?T.wrapper.children("."+T.params.slideClass+":not(."+T.params.slideDuplicateClass+')[data-swiper-slide-index="'+T.realIndex+'"]').addClass(T.params.slideDuplicateActiveClass):T.wrapper.children("."+T.params.slideClass+"."+T.params.slideDuplicateClass+'[data-swiper-slide-index="'+T.realIndex+'"]').addClass(T.params.slideDuplicateActiveClass));var t=a.next("."+T.params.slideClass).addClass(T.params.slideNextClass);T.params.loop&&0===t.length&&(t=T.slides.eq(0),t.addClass(T.params.slideNextClass));var s=a.prev("."+T.params.slideClass).addClass(T.params.slidePrevClass);if(T.params.loop&&0===s.length&&(s=T.slides.eq(-1),s.addClass(T.params.slidePrevClass)),i.loop&&(t.hasClass(T.params.slideDuplicateClass)?T.wrapper.children("."+T.params.slideClass+":not(."+T.params.slideDuplicateClass+')[data-swiper-slide-index="'+t.attr("data-swiper-slide-index")+'"]').addClass(T.params.slideDuplicateNextClass):T.wrapper.children("."+T.params.slideClass+"."+T.params.slideDuplicateClass+'[data-swiper-slide-index="'+t.attr("data-swiper-slide-index")+'"]').addClass(T.params.slideDuplicateNextClass),s.hasClass(T.params.slideDuplicateClass)?T.wrapper.children("."+T.params.slideClass+":not(."+T.params.slideDuplicateClass+')[data-swiper-slide-index="'+s.attr("data-swiper-slide-index")+'"]').addClass(T.params.slideDuplicatePrevClass):T.wrapper.children("."+T.params.slideClass+"."+T.params.slideDuplicateClass+'[data-swiper-slide-index="'+s.attr("data-swiper-slide-index")+'"]').addClass(T.params.slideDuplicatePrevClass)),T.paginationContainer&&T.paginationContainer.length>0){var r,n=T.params.loop?Math.ceil((T.slides.length-2*T.loopedSlides)/T.params.slidesPerGroup):T.snapGrid.length;if(T.params.loop?(r=Math.ceil((T.activeIndex-T.loopedSlides)/T.params.slidesPerGroup),r>T.slides.length-1-2*T.loopedSlides&&(r-=T.slides.length-2*T.loopedSlides),r>n-1&&(r-=n),r<0&&"bullets"!==T.params.paginationType&&(r=n+r)):r=void 0!==T.snapIndex?T.snapIndex:T.activeIndex||0,"bullets"===T.params.paginationType&&T.bullets&&T.bullets.length>0&&(T.bullets.removeClass(T.params.bulletActiveClass),T.paginationContainer.length>1?T.bullets.each(function(){e(this).index()===r&&e(this).addClass(T.params.bulletActiveClass)}):T.bullets.eq(r).addClass(T.params.bulletActiveClass)),"fraction"===T.params.paginationType&&(T.paginationContainer.find("."+T.params.paginationCurrentClass).text(r+1),T.paginationContainer.find("."+T.params.paginationTotalClass).text(n)),"progress"===T.params.paginationType){var o=(r+1)/n,l=o,p=1;T.isHorizontal()||(p=o,l=1),T.paginationContainer.find("."+T.params.paginationProgressbarClass).transform("translate3d(0,0,0) scaleX("+l+") scaleY("+p+")").transition(T.params.speed)}"custom"===T.params.paginationType&&T.params.paginationCustomRender&&(T.paginationContainer.html(T.params.paginationCustomRender(T,r+1,n)),T.emit("onPaginationRendered",T,T.paginationContainer[0]))}T.params.loop||(T.params.prevButton&&T.prevButton&&T.prevButton.length>0&&(T.isBeginning?(T.prevButton.addClass(T.params.buttonDisabledClass),T.params.a11y&&T.a11y&&T.a11y.disable(T.prevButton)):(T.prevButton.removeClass(T.params.buttonDisabledClass),T.params.a11y&&T.a11y&&T.a11y.enable(T.prevButton))),T.params.nextButton&&T.nextButton&&T.nextButton.length>0&&(T.isEnd?(T.nextButton.addClass(T.params.buttonDisabledClass),T.params.a11y&&T.a11y&&T.a11y.disable(T.nextButton)):(T.nextButton.removeClass(T.params.buttonDisabledClass),T.params.a11y&&T.a11y&&T.a11y.enable(T.nextButton))))},T.updatePagination=function(){if(T.params.pagination&&T.paginationContainer&&T.paginationContainer.length>0){var e="";if("bullets"===T.params.paginationType){for(var a=T.params.loop?Math.ceil((T.slides.length-2*T.loopedSlides)/T.params.slidesPerGroup):T.snapGrid.length,t=0;t";T.paginationContainer.html(e),T.bullets=T.paginationContainer.find("."+T.params.bulletClass),T.params.paginationClickable&&T.params.a11y&&T.a11y&&T.a11y.initPagination()}"fraction"===T.params.paginationType&&(e=T.params.paginationFractionRender?T.params.paginationFractionRender(T,T.params.paginationCurrentClass,T.params.paginationTotalClass):' / ',T.paginationContainer.html(e)),"progress"===T.params.paginationType&&(e=T.params.paginationProgressRender?T.params.paginationProgressRender(T,T.params.paginationProgressbarClass):'',T.paginationContainer.html(e)),"custom"!==T.params.paginationType&&T.emit("onPaginationRendered",T,T.paginationContainer[0])}},T.update=function(e){function a(){T.rtl,T.translate;t=Math.min(Math.max(T.translate,T.maxTranslate()),T.minTranslate()),T.setWrapperTranslate(t),T.updateActiveIndex(),T.updateClasses()}if(T){T.updateContainerSize(),T.updateSlidesSize(),T.updateProgress(),T.updatePagination(),T.updateClasses(),T.params.scrollbar&&T.scrollbar&&T.scrollbar.set();var t;if(e){T.controller&&T.controller.spline&&(T.controller.spline=void 0),T.params.freeMode?(a(),T.params.autoHeight&&T.updateAutoHeight()):(("auto"===T.params.slidesPerView||T.params.slidesPerView>1)&&T.isEnd&&!T.params.centeredSlides?T.slideTo(T.slides.length-1,0,!1,!0):T.slideTo(T.activeIndex,0,!1,!0))||a()}else T.params.autoHeight&&T.updateAutoHeight()}},T.onResize=function(e){T.params.onBeforeResize&&T.params.onBeforeResize(T),T.params.breakpoints&&T.setBreakpoint();var a=T.params.allowSwipeToPrev,t=T.params.allowSwipeToNext;T.params.allowSwipeToPrev=T.params.allowSwipeToNext=!0,T.updateContainerSize(),T.updateSlidesSize(),("auto"===T.params.slidesPerView||T.params.freeMode||e)&&T.updatePagination(),T.params.scrollbar&&T.scrollbar&&T.scrollbar.set(),T.controller&&T.controller.spline&&(T.controller.spline=void 0);var s=!1;if(T.params.freeMode){var i=Math.min(Math.max(T.translate,T.maxTranslate()),T.minTranslate());T.setWrapperTranslate(i),T.updateActiveIndex(),T.updateClasses(),T.params.autoHeight&&T.updateAutoHeight()}else T.updateClasses(),s=("auto"===T.params.slidesPerView||T.params.slidesPerView>1)&&T.isEnd&&!T.params.centeredSlides?T.slideTo(T.slides.length-1,0,!1,!0):T.slideTo(T.activeIndex,0,!1,!0);T.params.lazyLoading&&!s&&T.lazy&&T.lazy.load(),T.params.allowSwipeToPrev=a,T.params.allowSwipeToNext=t,T.params.onAfterResize&&T.params.onAfterResize(T)},T.touchEventsDesktop={start:"mousedown",move:"mousemove",end:"mouseup"},window.navigator.pointerEnabled?T.touchEventsDesktop={start:"pointerdown",move:"pointermove",end:"pointerup"}:window.navigator.msPointerEnabled&&(T.touchEventsDesktop={start:"MSPointerDown",move:"MSPointerMove",end:"MSPointerUp"}),T.touchEvents={start:T.support.touch||!T.params.simulateTouch?"touchstart":T.touchEventsDesktop.start,move:T.support.touch||!T.params.simulateTouch?"touchmove":T.touchEventsDesktop.move,end:T.support.touch||!T.params.simulateTouch?"touchend":T.touchEventsDesktop.end},(window.navigator.pointerEnabled||window.navigator.msPointerEnabled)&&("container"===T.params.touchEventsTarget?T.container:T.wrapper).addClass("swiper-wp8-"+T.params.direction),T.initEvents=function(e){var a=e?"off":"on",t=e?"removeEventListener":"addEventListener",s="container"===T.params.touchEventsTarget?T.container[0]:T.wrapper[0],r=T.support.touch?s:document,n=!!T.params.nested;if(T.browser.ie)s[t](T.touchEvents.start,T.onTouchStart,!1),r[t](T.touchEvents.move,T.onTouchMove,n),r[t](T.touchEvents.end,T.onTouchEnd,!1);else{if(T.support.touch){var o=!("touchstart"!==T.touchEvents.start||!T.support.passiveListener||!T.params.passiveListeners)&&{passive:!0,capture:!1};s[t](T.touchEvents.start,T.onTouchStart,o),s[t](T.touchEvents.move,T.onTouchMove,n),s[t](T.touchEvents.end,T.onTouchEnd,o)}(i.simulateTouch&&!T.device.ios&&!T.device.android||i.simulateTouch&&!T.support.touch&&T.device.ios)&&(s[t]("mousedown",T.onTouchStart,!1),document[t]("mousemove",T.onTouchMove,n),document[t]("mouseup",T.onTouchEnd,!1))}window[t]("resize",T.onResize),T.params.nextButton&&T.nextButton&&T.nextButton.length>0&&(T.nextButton[a]("click",T.onClickNext),T.params.a11y&&T.a11y&&T.nextButton[a]("keydown",T.a11y.onEnterKey)),T.params.prevButton&&T.prevButton&&T.prevButton.length>0&&(T.prevButton[a]("click",T.onClickPrev),T.params.a11y&&T.a11y&&T.prevButton[a]("keydown",T.a11y.onEnterKey)),T.params.pagination&&T.params.paginationClickable&&(T.paginationContainer[a]("click","."+T.params.bulletClass,T.onClickIndex),T.params.a11y&&T.a11y&&T.paginationContainer[a]("keydown","."+T.params.bulletClass,T.a11y.onEnterKey)),(T.params.preventClicks||T.params.preventClicksPropagation)&&s[t]("click",T.preventClicks,!0)},T.attachEvents=function(){T.initEvents()},T.detachEvents=function(){T.initEvents(!0)},T.allowClick=!0,T.preventClicks=function(e){T.allowClick||(T.params.preventClicks&&e.preventDefault(),T.params.preventClicksPropagation&&T.animating&&(e.stopPropagation(),e.stopImmediatePropagation()))},T.onClickNext=function(e){e.preventDefault(),T.isEnd&&!T.params.loop||T.slideNext()},T.onClickPrev=function(e){e.preventDefault(),T.isBeginning&&!T.params.loop||T.slidePrev()},T.onClickIndex=function(a){a.preventDefault();var t=e(this).index()*T.params.slidesPerGroup;T.params.loop&&(t+=T.loopedSlides),T.slideTo(t)}, +T.updateClickedSlide=function(a){var t=o(a,"."+T.params.slideClass),s=!1;if(t)for(var i=0;iT.slides.length-T.loopedSlides+l/2?(T.fixLoop(),n=T.wrapper.children("."+T.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.'+T.params.slideDuplicateClass+")").eq(0).index(),setTimeout(function(){T.slideTo(n)},0)):T.slideTo(n):n>T.slides.length-l?(T.fixLoop(),n=T.wrapper.children("."+T.params.slideClass+'[data-swiper-slide-index="'+r+'"]:not(.'+T.params.slideDuplicateClass+")").eq(0).index(),setTimeout(function(){T.slideTo(n)},0)):T.slideTo(n)}else T.slideTo(n)}};var S,C,z,M,E,P,I,k,L,D,B="input, select, textarea, button, video",H=Date.now(),G=[];T.animating=!1,T.touches={startX:0,startY:0,currentX:0,currentY:0,diff:0};var X,A;T.onTouchStart=function(a){if(a.originalEvent&&(a=a.originalEvent),(X="touchstart"===a.type)||!("which"in a)||3!==a.which){if(T.params.noSwiping&&o(a,"."+T.params.noSwipingClass))return void(T.allowClick=!0);if(!T.params.swipeHandler||o(a,T.params.swipeHandler)){var t=T.touches.currentX="touchstart"===a.type?a.targetTouches[0].pageX:a.pageX,s=T.touches.currentY="touchstart"===a.type?a.targetTouches[0].pageY:a.pageY;if(!(T.device.ios&&T.params.iOSEdgeSwipeDetection&&t<=T.params.iOSEdgeSwipeThreshold)){if(S=!0,C=!1,z=!0,E=void 0,A=void 0,T.touches.startX=t,T.touches.startY=s,M=Date.now(),T.allowClick=!0,T.updateContainerSize(),T.swipeDirection=void 0,T.params.threshold>0&&(k=!1),"touchstart"!==a.type){var i=!0;e(a.target).is(B)&&(i=!1),document.activeElement&&e(document.activeElement).is(B)&&document.activeElement.blur(),i&&a.preventDefault()}T.emit("onTouchStart",T,a)}}}},T.onTouchMove=function(a){if(a.originalEvent&&(a=a.originalEvent),!X||"mousemove"!==a.type){if(a.preventedByNestedSwiper)return T.touches.startX="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,void(T.touches.startY="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY);if(T.params.onlyExternal)return T.allowClick=!1,void(S&&(T.touches.startX=T.touches.currentX="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,T.touches.startY=T.touches.currentY="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY,M=Date.now()));if(X&&T.params.touchReleaseOnEdges&&!T.params.loop)if(T.isHorizontal()){if(T.touches.currentXT.touches.startX&&T.translate>=T.minTranslate())return}else if(T.touches.currentYT.touches.startY&&T.translate>=T.minTranslate())return;if(X&&document.activeElement&&a.target===document.activeElement&&e(a.target).is(B))return C=!0,void(T.allowClick=!1);if(z&&T.emit("onTouchMove",T,a),!(a.targetTouches&&a.targetTouches.length>1)){if(T.touches.currentX="touchmove"===a.type?a.targetTouches[0].pageX:a.pageX,T.touches.currentY="touchmove"===a.type?a.targetTouches[0].pageY:a.pageY,void 0===E){var t;T.isHorizontal()&&T.touches.currentY===T.touches.startY||!T.isHorizontal()&&T.touches.currentX===T.touches.startX?E=!1:(t=180*Math.atan2(Math.abs(T.touches.currentY-T.touches.startY),Math.abs(T.touches.currentX-T.touches.startX))/Math.PI,E=T.isHorizontal()?t>T.params.touchAngle:90-t>T.params.touchAngle)}if(E&&T.emit("onTouchMoveOpposite",T,a),void 0===A&&(T.touches.currentX===T.touches.startX&&T.touches.currentY===T.touches.startY||(A=!0)),S){if(E)return void(S=!1);if(A){T.allowClick=!1,T.emit("onSliderMove",T,a),a.preventDefault(),T.params.touchMoveStopPropagation&&!T.params.nested&&a.stopPropagation(),C||(i.loop&&T.fixLoop(),I=T.getWrapperTranslate(),T.setWrapperTransition(0),T.animating&&T.wrapper.trigger("webkitTransitionEnd transitionend oTransitionEnd MSTransitionEnd msTransitionEnd"),T.params.autoplay&&T.autoplaying&&(T.params.autoplayDisableOnInteraction?T.stopAutoplay():T.pauseAutoplay()),D=!1,!T.params.grabCursor||T.params.allowSwipeToNext!==!0&&T.params.allowSwipeToPrev!==!0||T.setGrabCursor(!0)),C=!0;var s=T.touches.diff=T.isHorizontal()?T.touches.currentX-T.touches.startX:T.touches.currentY-T.touches.startY;s*=T.params.touchRatio,T.rtl&&(s=-s),T.swipeDirection=s>0?"prev":"next",P=s+I;var r=!0;if(s>0&&P>T.minTranslate()?(r=!1,T.params.resistance&&(P=T.minTranslate()-1+Math.pow(-T.minTranslate()+I+s,T.params.resistanceRatio))):s<0&&PI&&(P=I),T.params.threshold>0){if(!(Math.abs(s)>T.params.threshold||k))return void(P=I);if(!k)return k=!0,T.touches.startX=T.touches.currentX,T.touches.startY=T.touches.currentY,P=I,void(T.touches.diff=T.isHorizontal()?T.touches.currentX-T.touches.startX:T.touches.currentY-T.touches.startY)}T.params.followFinger&&((T.params.freeMode||T.params.watchSlidesProgress)&&T.updateActiveIndex(),T.params.freeMode&&(0===G.length&&G.push({position:T.touches[T.isHorizontal()?"startX":"startY"],time:M}),G.push({position:T.touches[T.isHorizontal()?"currentX":"currentY"],time:(new window.Date).getTime()})),T.updateProgress(P),T.setWrapperTranslate(P))}}}}},T.onTouchEnd=function(a){if(a.originalEvent&&(a=a.originalEvent),z&&T.emit("onTouchEnd",T,a),z=!1,S){T.params.grabCursor&&C&&S&&(T.params.allowSwipeToNext===!0||T.params.allowSwipeToPrev===!0)&&T.setGrabCursor(!1);var t=Date.now(),s=t-M;if(T.allowClick&&(T.updateClickedSlide(a),T.emit("onTap",T,a),s<300&&t-H>300&&(L&&clearTimeout(L),L=setTimeout(function(){T&&(T.params.paginationHide&&T.paginationContainer.length>0&&!e(a.target).hasClass(T.params.bulletClass)&&T.paginationContainer.toggleClass(T.params.paginationHiddenClass),T.emit("onClick",T,a))},300)),s<300&&t-H<300&&(L&&clearTimeout(L),T.emit("onDoubleTap",T,a))),H=Date.now(),setTimeout(function(){T&&(T.allowClick=!0)},0),!S||!C||!T.swipeDirection||0===T.touches.diff||P===I)return void(S=C=!1);S=C=!1;var i;if(i=T.params.followFinger?T.rtl?T.translate:-T.translate:-P,T.params.freeMode){if(i<-T.minTranslate())return void T.slideTo(T.activeIndex);if(i>-T.maxTranslate())return void(T.slides.length1){var r=G.pop(),n=G.pop(),o=r.position-n.position,l=r.time-n.time;T.velocity=o/l,T.velocity=T.velocity/2,Math.abs(T.velocity)150||(new window.Date).getTime()-r.time>300)&&(T.velocity=0)}else T.velocity=0;T.velocity=T.velocity*T.params.freeModeMomentumVelocityRatio,G.length=0;var p=1e3*T.params.freeModeMomentumRatio,d=T.velocity*p,u=T.translate+d;T.rtl&&(u=-u);var c,m=!1,h=20*Math.abs(T.velocity)*T.params.freeModeMomentumBounceRatio;if(uT.minTranslate())T.params.freeModeMomentumBounce?(u-T.minTranslate()>h&&(u=T.minTranslate()+h),c=T.minTranslate(),m=!0,D=!0):u=T.minTranslate();else if(T.params.freeModeSticky){var g,f=0;for(f=0;f-u){g=f;break}u=Math.abs(T.snapGrid[g]-u)=T.params.longSwipesMs)&&(T.updateProgress(),T.updateActiveIndex()))}var v,w=0,y=T.slidesSizesGrid[0];for(v=0;v=T.slidesGrid[v]&&i=T.slidesGrid[v]&&(w=v,y=T.slidesGrid[T.slidesGrid.length-1]-T.slidesGrid[T.slidesGrid.length-2]);var x=(i-T.slidesGrid[w])/y;if(s>T.params.longSwipesMs){if(!T.params.longSwipes)return void T.slideTo(T.activeIndex);"next"===T.swipeDirection&&(x>=T.params.longSwipesRatio?T.slideTo(w+T.params.slidesPerGroup):T.slideTo(w)),"prev"===T.swipeDirection&&(x>1-T.params.longSwipesRatio?T.slideTo(w+T.params.slidesPerGroup):T.slideTo(w))}else{if(!T.params.shortSwipes)return void T.slideTo(T.activeIndex);"next"===T.swipeDirection&&T.slideTo(w+T.params.slidesPerGroup),"prev"===T.swipeDirection&&T.slideTo(w)}}},T._slideTo=function(e,a){return T.slideTo(e,a,!0,!0)},T.slideTo=function(e,a,t,s){void 0===t&&(t=!0),void 0===e&&(e=0),e<0&&(e=0),T.snapIndex=Math.floor(e/T.params.slidesPerGroup),T.snapIndex>=T.snapGrid.length&&(T.snapIndex=T.snapGrid.length-1);var i=-T.snapGrid[T.snapIndex];if(T.params.autoplay&&T.autoplaying&&(s||!T.params.autoplayDisableOnInteraction?T.pauseAutoplay(a):T.stopAutoplay()),T.updateProgress(i),T.params.normalizeSlideIndex)for(var r=0;r=Math.floor(100*T.slidesGrid[r])&&(e=r);return!(!T.params.allowSwipeToNext&&iT.translate&&i>T.maxTranslate()&&(T.activeIndex||0)!==e)&&(void 0===a&&(a=T.params.speed),T.previousIndex=T.activeIndex||0,T.activeIndex=e,T.updateRealIndex(),T.rtl&&-i===T.translate||!T.rtl&&i===T.translate?(T.params.autoHeight&&T.updateAutoHeight(),T.updateClasses(),"slide"!==T.params.effect&&T.setWrapperTranslate(i),!1):(T.updateClasses(),T.onTransitionStart(t),0===a||T.browser.lteIE9?(T.setWrapperTranslate(i),T.setWrapperTransition(0),T.onTransitionEnd(t)):(T.setWrapperTranslate(i),T.setWrapperTransition(a),T.animating||(T.animating=!0,T.wrapper.transitionEnd(function(){T&&T.onTransitionEnd(t)}))),!0)))},T.onTransitionStart=function(e){void 0===e&&(e=!0),T.params.autoHeight&&T.updateAutoHeight(),T.lazy&&T.lazy.onTransitionStart(),e&&(T.emit("onTransitionStart",T),T.activeIndex!==T.previousIndex&&(T.emit("onSlideChangeStart",T),T.activeIndex>T.previousIndex?T.emit("onSlideNextStart",T):T.emit("onSlidePrevStart",T)))},T.onTransitionEnd=function(e){T.animating=!1,T.setWrapperTransition(0),void 0===e&&(e=!0),T.lazy&&T.lazy.onTransitionEnd(),e&&(T.emit("onTransitionEnd",T),T.activeIndex!==T.previousIndex&&(T.emit("onSlideChangeEnd",T),T.activeIndex>T.previousIndex?T.emit("onSlideNextEnd",T):T.emit("onSlidePrevEnd",T))),T.params.history&&T.history&&T.history.setHistory(T.params.history,T.activeIndex),T.params.hashnav&&T.hashnav&&T.hashnav.setHash()},T.slideNext=function(e,a,t){if(T.params.loop){if(T.animating)return!1;T.fixLoop();T.container[0].clientLeft;return T.slideTo(T.activeIndex+T.params.slidesPerGroup,a,e,t)}return T.slideTo(T.activeIndex+T.params.slidesPerGroup,a,e,t)},T._slideNext=function(e){return T.slideNext(!0,e,!0)},T.slidePrev=function(e,a,t){if(T.params.loop){if(T.animating)return!1;T.fixLoop();T.container[0].clientLeft;return T.slideTo(T.activeIndex-1,a,e,t)}return T.slideTo(T.activeIndex-1,a,e,t)},T._slidePrev=function(e){return T.slidePrev(!0,e,!0)},T.slideReset=function(e,a,t){return T.slideTo(T.activeIndex,a,e)},T.disableTouchControl=function(){return T.params.onlyExternal=!0,!0},T.enableTouchControl=function(){return T.params.onlyExternal=!1,!0},T.setWrapperTransition=function(e,a){T.wrapper.transition(e),"slide"!==T.params.effect&&T.effects[T.params.effect]&&T.effects[T.params.effect].setTransition(e),T.params.parallax&&T.parallax&&T.parallax.setTransition(e),T.params.scrollbar&&T.scrollbar&&T.scrollbar.setTransition(e),T.params.control&&T.controller&&T.controller.setTransition(e,a),T.emit("onSetTransition",T,e)},T.setWrapperTranslate=function(e,a,t){var s=0,i=0;T.isHorizontal()?s=T.rtl?-e:e:i=e,T.params.roundLengths&&(s=r(s),i=r(i)),T.params.virtualTranslate||(T.support.transforms3d?T.wrapper.transform("translate3d("+s+"px, "+i+"px, 0px)"):T.wrapper.transform("translate("+s+"px, "+i+"px)")),T.translate=T.isHorizontal()?s:i;var n,o=T.maxTranslate()-T.minTranslate();n=0===o?0:(e-T.minTranslate())/o,n!==T.progress&&T.updateProgress(e),a&&T.updateActiveIndex(),"slide"!==T.params.effect&&T.effects[T.params.effect]&&T.effects[T.params.effect].setTranslate(T.translate),T.params.parallax&&T.parallax&&T.parallax.setTranslate(T.translate),T.params.scrollbar&&T.scrollbar&&T.scrollbar.setTranslate(T.translate),T.params.control&&T.controller&&T.controller.setTranslate(T.translate,t),T.emit("onSetTranslate",T,T.translate)},T.getTranslate=function(e,a){var t,s,i,r;return void 0===a&&(a="x"),T.params.virtualTranslate?T.rtl?-T.translate:T.translate:(i=window.getComputedStyle(e,null),window.WebKitCSSMatrix?(s=i.transform||i.webkitTransform,s.split(",").length>6&&(s=s.split(", ").map(function(e){return e.replace(",",".")}).join(", ")),r=new window.WebKitCSSMatrix("none"===s?"":s)):(r=i.MozTransform||i.OTransform||i.MsTransform||i.msTransform||i.transform||i.getPropertyValue("transform").replace("translate(","matrix(1, 0, 0, 1,"),t=r.toString().split(",")),"x"===a&&(s=window.WebKitCSSMatrix?r.m41:16===t.length?parseFloat(t[12]):parseFloat(t[4])),"y"===a&&(s=window.WebKitCSSMatrix?r.m42:16===t.length?parseFloat(t[13]):parseFloat(t[5])),T.rtl&&s&&(s=-s),s||0)},T.getWrapperTranslate=function(e){return void 0===e&&(e=T.isHorizontal()?"x":"y"),T.getTranslate(T.wrapper[0],e)},T.observers=[],T.initObservers=function(){if(T.params.observeParents)for(var e=T.container.parents(),a=0;aa.length&&(T.loopedSlides=a.length);var t,s=[],i=[];for(a.each(function(t,r){var n=e(this);t=a.length-T.loopedSlides&&s.push(r),n.attr("data-swiper-slide-index",t)}),t=0;t=0;t--)T.wrapper.prepend(e(s[t].cloneNode(!0)).addClass(T.params.slideDuplicateClass))},T.destroyLoop=function(){T.wrapper.children("."+T.params.slideClass+"."+T.params.slideDuplicateClass).remove(),T.slides.removeAttr("data-swiper-slide-index")},T.reLoop=function(e){var a=T.activeIndex-T.loopedSlides;T.destroyLoop(),T.createLoop(),T.updateSlidesSize(),e&&T.slideTo(a+T.loopedSlides,0,!1)},T.fixLoop=function(){var e;T.activeIndex=2*T.loopedSlides||T.activeIndex>T.slides.length-2*T.params.slidesPerView)&&(e=-T.slides.length+T.activeIndex+T.loopedSlides,e+=T.loopedSlides,T.slideTo(e,0,!1,!0))},T.appendSlide=function(e){if(T.params.loop&&T.destroyLoop(),"object"==typeof e&&e.length)for(var a=0;a
    '),t.append(d)),0===u.length&&(u=e('
    '),t.append(u)),d.length&&(d[0].style.opacity=Math.max(-s,0)),u.length&&(u[0].style.opacity=Math.max(s,0))}t.transform("translate3d("+l+"px, "+p+"px, 0px) rotateX("+o+"deg) rotateY("+n+"deg)")}},setTransition:function(a){if(T.slides.transition(a).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(a),T.params.virtualTranslate&&0!==a){var t=!1;T.slides.eq(T.activeIndex).transitionEnd(function(){if(!t&&T&&e(this).hasClass(T.params.slideActiveClass)){t=!0,T.animating=!1;for(var a=["webkitTransitionEnd","transitionend","oTransitionEnd","MSTransitionEnd","msTransitionEnd"],s=0;s
    '),T.wrapper.append(a)),a.css({height:T.width+"px"})):(a=T.container.find(".swiper-cube-shadow"),0===a.length&&(a=e('
    '),T.container.append(a))));for(var s=0;s-1&&(t=90*s+90*o,T.rtl&&(t=90*-s-90*o)),i.transform(u),T.params.cube.slideShadows){var c=T.isHorizontal()?i.find(".swiper-slide-shadow-left"):i.find(".swiper-slide-shadow-top"),m=T.isHorizontal()?i.find(".swiper-slide-shadow-right"):i.find(".swiper-slide-shadow-bottom");0===c.length&&(c=e('
    '),i.append(c)),0===m.length&&(m=e('
    '),i.append(m)),c.length&&(c[0].style.opacity=Math.max(-o,0)),m.length&&(m[0].style.opacity=Math.max(o,0))}}if(T.wrapper.css({"-webkit-transform-origin":"50% 50% -"+T.size/2+"px","-moz-transform-origin":"50% 50% -"+T.size/2+"px","-ms-transform-origin":"50% 50% -"+T.size/2+"px","transform-origin":"50% 50% -"+T.size/2+"px"}),T.params.cube.shadow)if(T.isHorizontal())a.transform("translate3d(0px, "+(T.width/2+T.params.cube.shadowOffset)+"px, "+-T.width/2+"px) rotateX(90deg) rotateZ(0deg) scale("+T.params.cube.shadowScale+")");else{var h=Math.abs(t)-90*Math.floor(Math.abs(t)/90),g=1.5-(Math.sin(2*h*Math.PI/360)/2+Math.cos(2*h*Math.PI/360)/2),f=T.params.cube.shadowScale,v=T.params.cube.shadowScale/g,w=T.params.cube.shadowOffset;a.transform("scale3d("+f+", 1, "+v+") translate3d(0px, "+(T.height/2+w)+"px, "+-T.height/2/v+"px) rotateX(-90deg)")}var y=T.isSafari||T.isUiWebView?-T.size/2:0;T.wrapper.transform("translate3d(0px,0,"+y+"px) rotateX("+(T.isHorizontal()?0:t)+"deg) rotateY("+(T.isHorizontal()?-t:0)+"deg)")},setTransition:function(e){T.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e),T.params.cube.shadow&&!T.isHorizontal()&&T.container.find(".swiper-cube-shadow").transition(e)}},coverflow:{setTranslate:function(){for(var a=T.translate,t=T.isHorizontal()?-a+T.width/2:-a+T.height/2,s=T.isHorizontal()?T.params.coverflow.rotate:-T.params.coverflow.rotate,i=T.params.coverflow.depth,r=0,n=T.slides.length;r'),o.append(v)),0===w.length&&(w=e('
    '),o.append(w)),v.length&&(v[0].style.opacity=d>0?d:0),w.length&&(w[0].style.opacity=-d>0?-d:0)}}if(T.browser.ie){T.wrapper[0].style.perspectiveOrigin=t+"px 50%"}},setTransition:function(e){T.slides.transition(e).find(".swiper-slide-shadow-top, .swiper-slide-shadow-right, .swiper-slide-shadow-bottom, .swiper-slide-shadow-left").transition(e)}}},T.lazy={initialImageLoaded:!1,loadImageInSlide:function(a,t){if(void 0!==a&&(void 0===t&&(t=!0),0!==T.slides.length)){var s=T.slides.eq(a),i=s.find("."+T.params.lazyLoadingClass+":not(."+T.params.lazyStatusLoadedClass+"):not(."+T.params.lazyStatusLoadingClass+")");!s.hasClass(T.params.lazyLoadingClass)||s.hasClass(T.params.lazyStatusLoadedClass)||s.hasClass(T.params.lazyStatusLoadingClass)||(i=i.add(s[0])),0!==i.length&&i.each(function(){var a=e(this);a.addClass(T.params.lazyStatusLoadingClass);var i=a.attr("data-background"),r=a.attr("data-src"),n=a.attr("data-srcset"),o=a.attr("data-sizes");T.loadImage(a[0],r||i,n,o,!1,function(){if(void 0!==T&&null!==T&&T){if(i?(a.css("background-image",'url("'+i+'")'),a.removeAttr("data-background")):(n&&(a.attr("srcset",n),a.removeAttr("data-srcset")),o&&(a.attr("sizes",o),a.removeAttr("data-sizes")),r&&(a.attr("src",r),a.removeAttr("data-src"))),a.addClass(T.params.lazyStatusLoadedClass).removeClass(T.params.lazyStatusLoadingClass),s.find("."+T.params.lazyPreloaderClass+", ."+T.params.preloaderClass).remove(),T.params.loop&&t){var e=s.attr("data-swiper-slide-index");if(s.hasClass(T.params.slideDuplicateClass)){var l=T.wrapper.children('[data-swiper-slide-index="'+e+'"]:not(.'+T.params.slideDuplicateClass+")");T.lazy.loadImageInSlide(l.index(),!1)}else{var p=T.wrapper.children("."+T.params.slideDuplicateClass+'[data-swiper-slide-index="'+e+'"]');T.lazy.loadImageInSlide(p.index(),!1)}}T.emit("onLazyImageReady",T,s[0],a[0])}}),T.emit("onLazyImageLoad",T,s[0],a[0])})}},load:function(){var a,t=T.params.slidesPerView;if("auto"===t&&(t=0),T.lazy.initialImageLoaded||(T.lazy.initialImageLoaded=!0),T.params.watchSlidesVisibility)T.wrapper.children("."+T.params.slideVisibleClass).each(function(){T.lazy.loadImageInSlide(e(this).index())});else if(t>1)for(a=T.activeIndex;a1||T.params.lazyLoadingInPrevNextAmount&&T.params.lazyLoadingInPrevNextAmount>1){var s=T.params.lazyLoadingInPrevNextAmount,i=t,r=Math.min(T.activeIndex+i+Math.max(s,i),T.slides.length),n=Math.max(T.activeIndex-Math.max(i,s),0);for(a=T.activeIndex+t;a0&&T.lazy.loadImageInSlide(o.index());var l=T.wrapper.children("."+T.params.slidePrevClass);l.length>0&&T.lazy.loadImageInSlide(l.index())}},onTransitionStart:function(){T.params.lazyLoading&&(T.params.lazyLoadingOnTransitionStart||!T.params.lazyLoadingOnTransitionStart&&!T.lazy.initialImageLoaded)&&T.lazy.load()},onTransitionEnd:function(){T.params.lazyLoading&&!T.params.lazyLoadingOnTransitionStart&&T.lazy.load()}},T.scrollbar={isTouched:!1,setDragPosition:function(e){var a=T.scrollbar,t=T.isHorizontal()?"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageX:e.pageX||e.clientX:"touchstart"===e.type||"touchmove"===e.type?e.targetTouches[0].pageY:e.pageY||e.clientY,s=t-a.track.offset()[T.isHorizontal()?"left":"top"]-a.dragSize/2,i=-T.minTranslate()*a.moveDivider,r=-T.maxTranslate()*a.moveDivider;sr&&(s=r),s=-s/a.moveDivider,T.updateProgress(s),T.setWrapperTranslate(s,!0)},dragStart:function(e){var a=T.scrollbar;a.isTouched=!0,e.preventDefault(),e.stopPropagation(),a.setDragPosition(e),clearTimeout(a.dragTimeout),a.track.transition(0),T.params.scrollbarHide&&a.track.css("opacity",1),T.wrapper.transition(100),a.drag.transition(100),T.emit("onScrollbarDragStart",T)},dragMove:function(e){var a=T.scrollbar;a.isTouched&&(e.preventDefault?e.preventDefault():e.returnValue=!1,a.setDragPosition(e),T.wrapper.transition(0),a.track.transition(0),a.drag.transition(0),T.emit("onScrollbarDragMove",T))},dragEnd:function(e){var a=T.scrollbar;a.isTouched&&(a.isTouched=!1,T.params.scrollbarHide&&(clearTimeout(a.dragTimeout),a.dragTimeout=setTimeout(function(){a.track.css("opacity",0),a.track.transition(400)},1e3)),T.emit("onScrollbarDragEnd",T),T.params.scrollbarSnapOnRelease&&T.slideReset())},draggableEvents:function(){return T.params.simulateTouch!==!1||T.support.touch?T.touchEvents:T.touchEventsDesktop}(),enableDraggable:function(){var a=T.scrollbar,t=T.support.touch?a.track:document;e(a.track).on(a.draggableEvents.start,a.dragStart),e(t).on(a.draggableEvents.move,a.dragMove),e(t).on(a.draggableEvents.end,a.dragEnd)},disableDraggable:function(){var a=T.scrollbar,t=T.support.touch?a.track:document;e(a.track).off(a.draggableEvents.start,a.dragStart),e(t).off(a.draggableEvents.move,a.dragMove),e(t).off(a.draggableEvents.end,a.dragEnd)},set:function(){if(T.params.scrollbar){var a=T.scrollbar;a.track=e(T.params.scrollbar),T.params.uniqueNavElements&&"string"==typeof T.params.scrollbar&&a.track.length>1&&1===T.container.find(T.params.scrollbar).length&&(a.track=T.container.find(T.params.scrollbar)),a.drag=a.track.find(".swiper-scrollbar-drag"),0===a.drag.length&&(a.drag=e('
    '),a.track.append(a.drag)),a.drag[0].style.width="",a.drag[0].style.height="",a.trackSize=T.isHorizontal()?a.track[0].offsetWidth:a.track[0].offsetHeight,a.divider=T.size/T.virtualSize,a.moveDivider=a.divider*(a.trackSize/T.size),a.dragSize=a.trackSize*a.divider,T.isHorizontal()?a.drag[0].style.width=a.dragSize+"px":a.drag[0].style.height=a.dragSize+"px",a.divider>=1?a.track[0].style.display="none":a.track[0].style.display="",T.params.scrollbarHide&&(a.track[0].style.opacity=0)}},setTranslate:function(){if(T.params.scrollbar){var e,a=T.scrollbar,t=(T.translate,a.dragSize);e=(a.trackSize-a.dragSize)*T.progress,T.rtl&&T.isHorizontal()?(e=-e,e>0?(t=a.dragSize-e,e=0):-e+a.dragSize>a.trackSize&&(t=a.trackSize+e)):e<0?(t=a.dragSize+e,e=0):e+a.dragSize>a.trackSize&&(t=a.trackSize-e),T.isHorizontal()?(T.support.transforms3d?a.drag.transform("translate3d("+e+"px, 0, 0)"):a.drag.transform("translateX("+e+"px)"),a.drag[0].style.width=t+"px"):(T.support.transforms3d?a.drag.transform("translate3d(0px, "+e+"px, 0)"):a.drag.transform("translateY("+e+"px)"),a.drag[0].style.height=t+"px"),T.params.scrollbarHide&&(clearTimeout(a.timeout),a.track[0].style.opacity=1,a.timeout=setTimeout(function(){a.track[0].style.opacity=0,a.track.transition(400)},1e3))}},setTransition:function(e){T.params.scrollbar&&T.scrollbar.drag.transition(e)}},T.controller={LinearSpline:function(e,a){var t=function(){var e,a,t;return function(s,i){for(a=-1,e=s.length;e-a>1;)s[t=e+a>>1]<=i?a=t:e=t;return e}}();this.x=e,this.y=a,this.lastIndex=e.length-1;var s,i;this.x.length;this.interpolate=function(e){return e?(i=t(this.x,e),s=i-1,(e-this.x[s])*(this.y[i]-this.y[s])/(this.x[i]-this.x[s])+this.y[s]):0}},getInterpolateFunction:function(e){T.controller.spline||(T.controller.spline=T.params.loop?new T.controller.LinearSpline(T.slidesGrid,e.slidesGrid):new T.controller.LinearSpline(T.snapGrid,e.snapGrid))},setTranslate:function(e,t){function s(a){e=a.rtl&&"horizontal"===a.params.direction?-T.translate:T.translate,"slide"===T.params.controlBy&&(T.controller.getInterpolateFunction(a),r=-T.controller.spline.interpolate(-e)),r&&"container"!==T.params.controlBy||(i=(a.maxTranslate()-a.minTranslate())/(T.maxTranslate()-T.minTranslate()),r=(e-T.minTranslate())*i+a.minTranslate()),T.params.controlInverse&&(r=a.maxTranslate()-r),a.updateProgress(r),a.setWrapperTranslate(r,!1,T),a.updateActiveIndex()}var i,r,n=T.params.control;if(Array.isArray(n))for(var o=0;o-1?"DOMMouseScroll":function(){var e="onwheel"in document;if(!e){var a=document.createElement("div");a.setAttribute("onwheel","return;"),e="function"==typeof a.onwheel}return!e&&document.implementation&&document.implementation.hasFeature&&document.implementation.hasFeature("","")!==!0&&(e=document.implementation.hasFeature("Events.wheel","3.0")),e}()?"wheel":"mousewheel"),T.disableMousewheelControl=function(){if(!T.mousewheel.event)return!1;var a=T.container;return"container"!==T.params.mousewheelEventsTarged&&(a=e(T.params.mousewheelEventsTarged)),a.off(T.mousewheel.event,u),T.params.mousewheelControl=!1,!0},T.enableMousewheelControl=function(){if(!T.mousewheel.event)return!1;var a=T.container;return"container"!==T.params.mousewheelEventsTarged&&(a=e(T.params.mousewheelEventsTarged)),a.on(T.mousewheel.event,u),T.params.mousewheelControl=!0,!0},T.parallax={setTranslate:function(){T.container.children("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){c(this,T.progress)}),T.slides.each(function(){var a=e(this);a.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){c(this,Math.min(Math.max(a[0].progress,-1),1))})})},setTransition:function(a){void 0===a&&(a=T.params.speed),T.container.find("[data-swiper-parallax], [data-swiper-parallax-x], [data-swiper-parallax-y]").each(function(){var t=e(this),s=parseInt(t.attr("data-swiper-parallax-duration"),10)||a;0===a&&(s=0),t.transition(s)})}},T.zoom={scale:1,currentScale:1,isScaling:!1,gesture:{slide:void 0,slideWidth:void 0,slideHeight:void 0,image:void 0,imageWrap:void 0,zoomMax:T.params.zoomMax},image:{isTouched:void 0,isMoved:void 0,currentX:void 0,currentY:void 0,minX:void 0,minY:void 0,maxX:void 0,maxY:void 0,width:void 0,height:void 0,startX:void 0,startY:void 0,touchesStart:{},touchesCurrent:{}},velocity:{x:void 0,y:void 0,prevPositionX:void 0,prevPositionY:void 0,prevTime:void 0},getDistanceBetweenTouches:function(e){if(e.targetTouches.length<2)return 1;var a=e.targetTouches[0].pageX,t=e.targetTouches[0].pageY,s=e.targetTouches[1].pageX,i=e.targetTouches[1].pageY;return Math.sqrt(Math.pow(s-a,2)+Math.pow(i-t,2))},onGestureStart:function(a){var t=T.zoom;if(!T.support.gestures){if("touchstart"!==a.type||"touchstart"===a.type&&a.targetTouches.length<2)return;t.gesture.scaleStart=t.getDistanceBetweenTouches(a)}if(!(t.gesture.slide&&t.gesture.slide.length||(t.gesture.slide=e(this),0===t.gesture.slide.length&&(t.gesture.slide=T.slides.eq(T.activeIndex)),t.gesture.image=t.gesture.slide.find("img, svg, canvas"),t.gesture.imageWrap=t.gesture.image.parent("."+T.params.zoomContainerClass),t.gesture.zoomMax=t.gesture.imageWrap.attr("data-swiper-zoom")||T.params.zoomMax,0!==t.gesture.imageWrap.length)))return void(t.gesture.image=void 0);t.gesture.image.transition(0),t.isScaling=!0},onGestureChange:function(e){var a=T.zoom;if(!T.support.gestures){if("touchmove"!==e.type||"touchmove"===e.type&&e.targetTouches.length<2)return;a.gesture.scaleMove=a.getDistanceBetweenTouches(e)}a.gesture.image&&0!==a.gesture.image.length&&(T.support.gestures?a.scale=e.scale*a.currentScale:a.scale=a.gesture.scaleMove/a.gesture.scaleStart*a.currentScale,a.scale>a.gesture.zoomMax&&(a.scale=a.gesture.zoomMax-1+Math.pow(a.scale-a.gesture.zoomMax+1,.5)),a.scalea.image.touchesStart.x)return void(a.image.isTouched=!1);if(!T.isHorizontal()&&Math.floor(a.image.minY)===Math.floor(a.image.startY)&&a.image.touchesCurrent.ya.image.touchesStart.y)return void(a.image.isTouched=!1)}e.preventDefault(),e.stopPropagation(),a.image.isMoved=!0,a.image.currentX=a.image.touchesCurrent.x-a.image.touchesStart.x+a.image.startX,a.image.currentY=a.image.touchesCurrent.y-a.image.touchesStart.y+a.image.startY,a.image.currentXa.image.maxX&&(a.image.currentX=a.image.maxX-1+Math.pow(a.image.currentX-a.image.maxX+1,.8)),a.image.currentYa.image.maxY&&(a.image.currentY=a.image.maxY-1+Math.pow(a.image.currentY-a.image.maxY+1,.8)),a.velocity.prevPositionX||(a.velocity.prevPositionX=a.image.touchesCurrent.x),a.velocity.prevPositionY||(a.velocity.prevPositionY=a.image.touchesCurrent.y),a.velocity.prevTime||(a.velocity.prevTime=Date.now()),a.velocity.x=(a.image.touchesCurrent.x-a.velocity.prevPositionX)/(Date.now()-a.velocity.prevTime)/2,a.velocity.y=(a.image.touchesCurrent.y-a.velocity.prevPositionY)/(Date.now()-a.velocity.prevTime)/2,Math.abs(a.image.touchesCurrent.x-a.velocity.prevPositionX)<2&&(a.velocity.x=0),Math.abs(a.image.touchesCurrent.y-a.velocity.prevPositionY)<2&&(a.velocity.y=0),a.velocity.prevPositionX=a.image.touchesCurrent.x,a.velocity.prevPositionY=a.image.touchesCurrent.y,a.velocity.prevTime=Date.now(),a.gesture.imageWrap.transform("translate3d("+a.image.currentX+"px, "+a.image.currentY+"px,0)")}}},onTouchEnd:function(e,a){var t=e.zoom;if(t.gesture.image&&0!==t.gesture.image.length){if(!t.image.isTouched||!t.image.isMoved)return t.image.isTouched=!1,void(t.image.isMoved=!1);t.image.isTouched=!1,t.image.isMoved=!1;var s=300,i=300,r=t.velocity.x*s,n=t.image.currentX+r,o=t.velocity.y*i,l=t.image.currentY+o;0!==t.velocity.x&&(s=Math.abs((n-t.image.currentX)/t.velocity.x)),0!==t.velocity.y&&(i=Math.abs((l-t.image.currentY)/t.velocity.y));var p=Math.max(s,i);t.image.currentX=n,t.image.currentY=l;var d=t.image.width*t.scale,u=t.image.height*t.scale;t.image.minX=Math.min(t.gesture.slideWidth/2-d/2,0),t.image.maxX=-t.image.minX,t.image.minY=Math.min(t.gesture.slideHeight/2-u/2,0),t.image.maxY=-t.image.minY,t.image.currentX=Math.max(Math.min(t.image.currentX,t.image.maxX),t.image.minX),t.image.currentY=Math.max(Math.min(t.image.currentY,t.image.maxY),t.image.minY),t.gesture.imageWrap.transition(p).transform("translate3d("+t.image.currentX+"px, "+t.image.currentY+"px,0)")}},onTransitionEnd:function(e){var a=e.zoom;a.gesture.slide&&e.previousIndex!==e.activeIndex&&(a.gesture.image.transform("translate3d(0,0,0) scale(1)"),a.gesture.imageWrap.transform("translate3d(0,0,0)"),a.gesture.slide=a.gesture.image=a.gesture.imageWrap=void 0,a.scale=a.currentScale=1)},toggleZoom:function(a,t){var s=a.zoom;if(s.gesture.slide||(s.gesture.slide=a.clickedSlide?e(a.clickedSlide):a.slides.eq(a.activeIndex),s.gesture.image=s.gesture.slide.find("img, svg, canvas"),s.gesture.imageWrap=s.gesture.image.parent("."+a.params.zoomContainerClass)),s.gesture.image&&0!==s.gesture.image.length){var i,r,n,o,l,p,d,u,c,m,h,g,f,v,w,y,x,T;void 0===s.image.touchesStart.x&&t?(i="touchend"===t.type?t.changedTouches[0].pageX:t.pageX,r="touchend"===t.type?t.changedTouches[0].pageY:t.pageY):(i=s.image.touchesStart.x,r=s.image.touchesStart.y),s.scale&&1!==s.scale?(s.scale=s.currentScale=1,s.gesture.imageWrap.transition(300).transform("translate3d(0,0,0)"),s.gesture.image.transition(300).transform("translate3d(0,0,0) scale(1)"),s.gesture.slide=void 0):(s.scale=s.currentScale=s.gesture.imageWrap.attr("data-swiper-zoom")||a.params.zoomMax,t?(x=s.gesture.slide[0].offsetWidth,T=s.gesture.slide[0].offsetHeight,n=s.gesture.slide.offset().left,o=s.gesture.slide.offset().top,l=n+x/2-i,p=o+T/2-r,c=s.gesture.image[0].offsetWidth,m=s.gesture.image[0].offsetHeight,h=c*s.scale,g=m*s.scale,f=Math.min(x/2-h/2,0),v=Math.min(T/2-g/2,0),w=-f,y=-v,d=l*s.scale,u=p*s.scale,dw&&(d=w),uy&&(u=y)):(d=0,u=0),s.gesture.imageWrap.transition(300).transform("translate3d("+d+"px, "+u+"px,0)"),s.gesture.image.transition(300).transform("translate3d(0,0,0) scale("+s.scale+")"))}},attachEvents:function(a){var t=a?"off":"on";if(T.params.zoom){var s=(T.slides,!("touchstart"!==T.touchEvents.start||!T.support.passiveListener||!T.params.passiveListeners)&&{passive:!0,capture:!1});T.support.gestures?(T.slides[t]("gesturestart",T.zoom.onGestureStart,s),T.slides[t]("gesturechange",T.zoom.onGestureChange,s),T.slides[t]("gestureend",T.zoom.onGestureEnd,s)):"touchstart"===T.touchEvents.start&&(T.slides[t](T.touchEvents.start,T.zoom.onGestureStart,s),T.slides[t](T.touchEvents.move,T.zoom.onGestureChange,s),T.slides[t](T.touchEvents.end,T.zoom.onGestureEnd,s)),T[t]("touchStart",T.zoom.onTouchStart),T.slides.each(function(a,s){e(s).find("."+T.params.zoomContainerClass).length>0&&e(s)[t](T.touchEvents.move,T.zoom.onTouchMove)}),T[t]("touchEnd",T.zoom.onTouchEnd),T[t]("transitionEnd",T.zoom.onTransitionEnd),T.params.zoomToggle&&T.on("doubleTap",T.zoom.toggleZoom)}},init:function(){T.zoom.attachEvents()},destroy:function(){T.zoom.attachEvents(!0)}},T._plugins=[];for(var Y in T.plugins){var O=T.plugins[Y](T,T.params[Y]);O&&T._plugins.push(O)}return T.callPlugins=function(e){for(var a=0;a'),notify:function(e){var a=T.a11y.liveRegion;0!==a.length&&(a.html(""),a.html(e))},init:function(){T.params.nextButton&&T.nextButton&&T.nextButton.length>0&&(T.a11y.makeFocusable(T.nextButton),T.a11y.addRole(T.nextButton,"button"),T.a11y.addLabel(T.nextButton,T.params.nextSlideMessage)),T.params.prevButton&&T.prevButton&&T.prevButton.length>0&&(T.a11y.makeFocusable(T.prevButton),T.a11y.addRole(T.prevButton,"button"),T.a11y.addLabel(T.prevButton,T.params.prevSlideMessage)),e(T.container).append(T.a11y.liveRegion)},initPagination:function(){T.params.pagination&&T.params.paginationClickable&&T.bullets&&T.bullets.length&&T.bullets.each(function(){var a=e(this);T.a11y.makeFocusable(a),T.a11y.addRole(a,"button"),T.a11y.addLabel(a,T.params.paginationBulletMessage.replace(/{{index}}/,a.index()+1))})},destroy:function(){T.a11y.liveRegion&&T.a11y.liveRegion.length>0&&T.a11y.liveRegion.remove()}},T.init=function(){T.params.loop&&T.createLoop(),T.updateContainerSize(),T.updateSlidesSize(),T.updatePagination(),T.params.scrollbar&&T.scrollbar&&(T.scrollbar.set(),T.params.scrollbarDraggable&&T.scrollbar.enableDraggable()),"slide"!==T.params.effect&&T.effects[T.params.effect]&&(T.params.loop||T.updateProgress(),T.effects[T.params.effect].setTranslate()),T.params.loop?T.slideTo(T.params.initialSlide+T.loopedSlides,0,T.params.runCallbacksOnInit):(T.slideTo(T.params.initialSlide,0,T.params.runCallbacksOnInit),0===T.params.initialSlide&&(T.parallax&&T.params.parallax&&T.parallax.setTranslate(),T.lazy&&T.params.lazyLoading&&(T.lazy.load(),T.lazy.initialImageLoaded=!0))),T.attachEvents(),T.params.observer&&T.support.observer&&T.initObservers(),T.params.preloadImages&&!T.params.lazyLoading&&T.preloadImages(),T.params.zoom&&T.zoom&&T.zoom.init(),T.params.autoplay&&T.startAutoplay(),T.params.keyboardControl&&T.enableKeyboardControl&&T.enableKeyboardControl(),T.params.mousewheelControl&&T.enableMousewheelControl&&T.enableMousewheelControl(),T.params.hashnavReplaceState&&(T.params.replaceState=T.params.hashnavReplaceState),T.params.history&&T.history&&T.history.init(),T.params.hashnav&&T.hashnav&&T.hashnav.init(),T.params.a11y&&T.a11y&&T.a11y.init(),T.emit("onInit",T)},T.cleanupStyles=function(){T.container.removeClass(T.classNames.join(" ")).removeAttr("style"),T.wrapper.removeAttr("style"),T.slides&&T.slides.length&&T.slides.removeClass([T.params.slideVisibleClass,T.params.slideActiveClass,T.params.slideNextClass,T.params.slidePrevClass].join(" ")).removeAttr("style").removeAttr("data-swiper-column").removeAttr("data-swiper-row"),T.paginationContainer&&T.paginationContainer.length&&T.paginationContainer.removeClass(T.params.paginationHiddenClass),T.bullets&&T.bullets.length&&T.bullets.removeClass(T.params.bulletActiveClass),T.params.prevButton&&e(T.params.prevButton).removeClass(T.params.buttonDisabledClass),T.params.nextButton&&e(T.params.nextButton).removeClass(T.params.buttonDisabledClass),T.params.scrollbar&&T.scrollbar&&(T.scrollbar.track&&T.scrollbar.track.length&&T.scrollbar.track.removeAttr("style"),T.scrollbar.drag&&T.scrollbar.drag.length&&T.scrollbar.drag.removeAttr("style"))},T.destroy=function(e,a){T.detachEvents(),T.stopAutoplay(),T.params.scrollbar&&T.scrollbar&&T.params.scrollbarDraggable&&T.scrollbar.disableDraggable(),T.params.loop&&T.destroyLoop(),a&&T.cleanupStyles(),T.disconnectObservers(),T.params.zoom&&T.zoom&&T.zoom.destroy(),T.params.keyboardControl&&T.disableKeyboardControl&&T.disableKeyboardControl(),T.params.mousewheelControl&&T.disableMousewheelControl&&T.disableMousewheelControl(),T.params.a11y&&T.a11y&&T.a11y.destroy(),T.params.history&&!T.params.replaceState&&window.removeEventListener("popstate",T.history.setHistoryPopState),T.params.hashnav&&T.hashnav&&T.hashnav.destroy(),T.emit("onDestroy"),e!==!1&&(T=null)},T.init(),T}};a.prototype={isSafari:function(){var e=window.navigator.userAgent.toLowerCase();return e.indexOf("safari")>=0&&e.indexOf("chrome")<0&&e.indexOf("android")<0}(),isUiWebView:/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(window.navigator.userAgent),isArray:function(e){return"[object Array]"===Object.prototype.toString.apply(e)},browser:{ie:window.navigator.pointerEnabled||window.navigator.msPointerEnabled,ieTouch:window.navigator.msPointerEnabled&&window.navigator.msMaxTouchPoints>1||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints>1,lteIE9:function(){var e=document.createElement("div");return e.innerHTML="",1===e.getElementsByTagName("i").length}()},device:function(){var e=window.navigator.userAgent,a=e.match(/(Android);?[\s\/]+([\d.]+)?/),t=e.match(/(iPad).*OS\s([\d_]+)/),s=e.match(/(iPod)(.*OS\s([\d_]+))?/),i=!t&&e.match(/(iPhone\sOS|iOS)\s([\d_]+)/);return{ios:t||i||s,android:a}}(),support:{touch:window.Modernizr&&Modernizr.touch===!0||function(){return!!("ontouchstart"in window||window.DocumentTouch&&document instanceof DocumentTouch)}(),transforms3d:window.Modernizr&&Modernizr.csstransforms3d===!0||function(){var e=document.createElement("div").style;return"webkitPerspective"in e||"MozPerspective"in e||"OPerspective"in e||"MsPerspective"in e||"perspective"in e}(),flexbox:function(){for(var e=document.createElement("div").style,a="alignItems webkitAlignItems webkitBoxAlign msFlexAlign mozBoxAlign webkitFlexDirection msFlexDirection mozBoxDirection mozBoxOrient webkitBoxDirection webkitBoxOrient".split(" "),t=0;t=0&&o.indexOf(">")>=0){var l="div";for(0===o.indexOf(":~]/)?(t||document).querySelectorAll(a):[document.getElementById(a.split("#")[1])],i=0;i0&&a[0].nodeType)for(i=0;i0?parseFloat(this.css("width")):null},outerWidth:function(e){return this.length>0?e?this[0].offsetWidth+parseFloat(this.css("margin-right"))+parseFloat(this.css("margin-left")):this[0].offsetWidth:null},height:function(){return this[0]===window?window.innerHeight:this.length>0?parseFloat(this.css("height")):null},outerHeight:function(e){return this.length>0?e?this[0].offsetHeight+parseFloat(this.css("margin-top"))+parseFloat(this.css("margin-bottom")):this[0].offsetHeight:null},offset:function(){if(this.length>0){var e=this[0],a=e.getBoundingClientRect(),t=document.body,s=e.clientTop||t.clientTop||0,i=e.clientLeft||t.clientLeft||0,r=window.pageYOffset||e.scrollTop,n=window.pageXOffset||e.scrollLeft;return{top:a.top+r-s,left:a.left+n-i}}return null},css:function(e,a){var t;if(1===arguments.length){if("string"!=typeof e){for(t=0;ts-1?new e([]):a<0?(t=s+a,new e(t<0?[]:[this[t]])):new e([this[a]])},append:function(a){var t,s;for(t=0;t=0;s--)this[t].insertBefore(i.childNodes[s],this[t].childNodes[0])}else if(a instanceof e)for(s=0;s1)for(var i=0;i1)for(var i=0;i0?t?this[0].nextElementSibling&&a(this[0].nextElementSibling).is(t)?[this[0].nextElementSibling]:[]:this[0].nextElementSibling?[this[0].nextElementSibling]:[]:[])},nextAll:function(t){var s=[],i=this[0];if(!i)return new e([]);for(;i.nextElementSibling;){var r=i.nextElementSibling;t?a(r).is(t)&&s.push(r):s.push(r),i=r}return new e(s)},prev:function(t){return new e(this.length>0?t?this[0].previousElementSibling&&a(this[0].previousElementSibling).is(t)?[this[0].previousElementSibling]:[]:this[0].previousElementSibling?[this[0].previousElementSibling]:[]:[])},prevAll:function(t){var s=[],i=this[0];if(!i)return new e([]);for(;i.previousElementSibling;){var r=i.previousElementSibling;t?a(r).is(t)&&s.push(r):s.push(r),i=r}return new e(s)},parent:function(e){for(var t=[],s=0;s0?e?this[0].offsetWidth+parseFloat(this.css("margin-right"))+parseFloat(this.css("margin-left")):this[0].offsetWidth:null})),window.Swiper=a}(),"undefined"!=typeof module?module.exports=window.Swiper:"function"==typeof define&&define.amd&&define([],function(){"use strict";return window.Swiper}); +//# sourceMappingURL=maps/swiper.min.js.map diff --git a/sitemap.html b/sitemap.html new file mode 100644 index 0000000..b7790ff --- /dev/null +++ b/sitemap.html @@ -0,0 +1,66 @@ + + + +
    +

    Start of Content

    +
    + + +
    +
    +
      +
    • COMPANY
    • +
    • -
    • +
    +
    +
    +
    + +
    +
    + COMPANY 》 SITEMAP +
    +
    + +
    + + + + \ No newline at end of file