출처 : http://blog.naver.com/baek2187/150110320251

codesign.zip

1. ActiveX 만들기

 

비주얼스튜디오에서 ActiveX 를 만드는 방법은 두가지가 있다.

응용프로그램 마법사로 프로젝트를 이용하여 MFC ActiveX Control 프로젝트 또는 ATL Project 프로젝트로 만든다.

  1. MFC ActiveX Control
    • 프로젝트 생성하고 빌드하면 .OCX 라는 DLL이 만들어진다. 이 OCX 파일을 CAB에 포함하여 웹페이지에 링크하면 된다.
    • MFC를 이용하여 컨트롤을 개발할 경우에는 OLE를 전혀 모르는 프로그래머들도 원하는 형태의 OCX 컨트롤을 구현하기 쉽다.
    • 단 지, MFC로 ActiveX를 만들면 코드 사이즈가 커지며, 그것은 MFC가 컨트롤에 대해서 COleControl 클래스를 기반으로 생성해 주기 때문에 기존의 OLE 컨트롤 사양에서 필수적으로 구현해 주도록 한 부분을 모두 포함하고 있기 때문이다. 또한, MFC의 부수적인 Run-time DLL도 오버헤드로 작용할 수 있다.
    • CAB 배포시 MFC관련 DLL을 함께 포함하고 inf 파일에 명시해야 한다.
  2. ATL Project
  • MFC 프로젝트에 비해 배포에 필요한 DLL 용량이 작아서 효율적이다.
  • MFC 프로젝트에 비해 컨트롤 구현을 ATL로 직접 구현해야 하기 때문에 비교적 힘들다.
  • MFC를 이용한 UI가 거의 없고 배포 용량을 줄이는 프로젝트 구현에 적합하다.

MFC 기반으로 ActiveX 만들기

  1. MFC ActiveX Control 프로젝트를 생성한다.
  2. 프로그래밍후 빌드하면 OCX 파일이 생성된다.
  3. MFC 메서드와 HTML과 메서드 커뮤니케이션시에 안전하지 않는 컨트롤 실행에 대한 윈도우 경고창이 뜰 경우 안정성을 보장하는 컨트롤 을 제작한다.

개발 참조:

ActiveX 강좌

MFC ActiveX 컨트롤 만들기

Visual studio 2008 에서 ActiveX만들기

ATL 기반으로 ActiveX 만들기

  1. ATL 프로젝트를 생성한다.
  2. 솔루션의 프로젝트에서 Add Class로 ATL Control을 하나 추가한다. (아래는 추가시 옵션이다)
    1. 추가시 Options
      • Control type: 보통은 Standard control로 설정한다. Windows Form과 비슷한 컨트롤을 작성하려면 Composite control을, DHTML을 호스팅해서 UI를 구성하려면 DHTML을 사용한다.
      • Minimal control: 최소한의 COM 인터페이스만을 구현하도록 한다. 이 예제는 IE에서만 동작하면 되므로 체크해 두었다. VB나 VC등으로 만든 다른 COM Host어플리케이션에서 사용되어야 하는 컨트롤이라면 체크하지 말자.
      • Connection points: 컨트롤이 외부에 이벤트를 공개해야 한다면 선택하자. 예제에서는 이벤트 사용 예제를 위해 체크해 두었다.
    2. 추가시 Interfaces
      • IObjectSafety: 컨트롤이 스크립트, 초기화 등에 안전함을 컨테이너가 인식할 수 있도록 한다.
      • IPropertyNotifySink: 컨트롤에서 변경된 속성을 즉시 사용할 수 있도록 해 준다.
      • IProvideClassInfo2: 이벤트 사용을 위해서는 반드시 필요하다. Connection Point를 구현하는 경우라면 반드시 포함시키자.
      • IQuickActivate: 콘트롤을 보다 빨리 활성화 시킨다.컨테이너는 컨트롤에 구현된 IQuickActivate::QuickActive메서드를 호출 QACOTAINER구조체정보를 매개변수로 컨트롤에 넘겨준다.
      • ISupportErrorInfo: 컨트롤에서 발생한 예외(Exception)을 컨테이너가 처리할 수 있도록 해 준다.

개발 참조:

ATL ActiveX 만들기 - Part1. 프로젝트 구성

ATL ActiveX 만들기 - Part2. 컨트롤 구현

ATL ActiveX 만들기 - Part3. 이벤트(Connection point) 구현

ATL ActiveX 만들기 - Part4. 관리자권한 UAC Elevation

안정성을 보장하는 ActiveX 컨트롤 만들기

MFC는 기본적으로 위자드에서 생성된 컨트롤에 스크립팅과 컨트롤 초기화를 위한 안전처리가 되어있다. IE에서 보안이 보통 이상인 경우 컨트롤이 안전하지 않다는 메시지가 출력될 것이다.

해결하는 방법은 두 가지로, IObjectSafety 인터페이스를 구현하는 것이고 다른 하나는 컨트롤의 DLLRegisterServer 함수안에 레지스트리에 안전표시를 하도록 하는 것이다.

HOWTO: MFC 컨트롤을 스크립트 사용에 안전(Safe for Scripting)/초기화에 안전(Safe for Initialization)으로 표시

안정성을 보장하는 ActiveX 컨트롤 제작

ActiveX Control 보안처리

액티브X 생성에서 배포까지

디버거 설정 및 디버깅하기

ActiveX 컨트롤은 웹페이지상에서 실행되기 때문에 일반 어플리케이션과는 디버깅을 다르게 설정해야 한다.

  1. 프로젝트 속성(Property)에서 Debugging - Debugger to launch 에서 Web Browser Debugger를 선택한다.
  2. HTTP URL 부분에 $(ProjectDir)컨트롤이름.htm 설정한다.
  3. F5로 디버거를 실행하면 브라우저가 뜨고 ActiveX 가 작동하며 디버깅이 가능해진다.

$(ProjectDir)는 프로젝트 파일이 저장되어있는 로컬 경로를 의미하며, 이곳에는 만들려고 하는 컨트롤의 OBJECT태그가 포함된 컨트롤이름.htm파일이 자동으로 생성되어 있다.

ActiveX 테스트를 위한 ActiveX Control Test Container 사용 방법

Visual Studio 2008 에는 작성된 Active X를 테스트를 위한 ActiveX Control Test Container 툴(TstCon32.exe)이 포함되어있지 않습니다.

VS 6.0에서는 기본 툴로 제공 되었으나 닷넷부터는 제공되지 않아 소스만 구할수 있으므로 빌드해야 한다.

첨부 파일에 실행파일만 첨부했지만 소스가 필요하다면 위에 제목으로 링크따라 가면 다운로드할 수 있다.

이제 ActiveX 프로젝트를 디버깅할 때 Executable For Debug Session 창의 Executable file name에 C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\TstCon32.exe 를 선택하여 사용 가능하다. (나중에 project property 창에서 Debugging > Command 에서 변경할 수 있다.)
C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools 폴더에 아래 첨부파일을 넣어서 사용한다.
또는, ActiveX를 Regsvr32 명령을 통해 OS에 등록 하신 후, 직접 TstCon32.exe 실행 후 Edit->insert New Controls ... 를 이용하시면 된다.

2. INF(.inf) 파일 만들기
섹션 편집

INF 파일은 컨트롤을 실행하거나 다운로드해야 하는 파일(DLL 또는 기타 OCX)을 지정하는 텍스트 파일이다. INF 파일을 사용하면 필요한 모든 파일을 하나의 압축된 CAB 파일로 묶을 수 있다. 기본적으로 사용자의 하드 디스크에 있는 기존 파일과 버전 번호가 같은 파일은 다운로드하지 않는다.

CAB 파일을 생성하기에 앞서 먼저 INF 파일을 만들어야 한다. INF 파일에는 Control과 함께 클라이언트측으로 다운로드 되어야 하는 파일들에 대한 정보가 저장된다. 비주얼 베이직은 자동으로 생성해주지만 VS일 경우 수동으로 메모장을 이용하여 작성해야 한다.

아래 내용은 inf 파일 예제이다. text.ocx 파일이 ActiveX 파일이며 기타 dll은 MFC 실행에 필요한 DLL 파일이다.

INF 파일 작성에 대한 자세한 내용은 아래 참조 링크를 보면 자세히 나와있다.

; ========================= test.inf ========================

; This .inf file will control the installation of the MFC test
; control. This control has been compiled with Visual C++ version 4.2.
; The FileVersion tags in the dependent DLLs section on this file
; reflect this requirement.

[version]
; version signature (same for both NT and Win95) do not remove
signature="$CHICAGO$"
AdvancedINF=2.0

[Add.Code]
test.ocx=test.ocx
; These are the necessary supporting DLLs for MFC 4.2 ActiveX Controls
mfc42.dll=mfc42.dll
msvcrt.dll=msvcrt.dll
olepro32.dll=olepro32.dll

; dependent DLLs
[msvcrt.dll]
; This is an example of conditional hook. The hook only gets processed
; if msvcrt.dll of the specified version is absent on client machine.
FileVersion=6,0,8168,0
hook=mfc42installer

[mfc42.dll]
FileVersion=6,0,8168,0
hook=mfc42installer

[olepro32.dll]
FileVersion=5,0,4261,0
hook=mfc42installer

[mfc42installer]
file-win32-x86=<LINK TYPE="GENERIC" VALUE="http://activex.microsoft.com
/controls/vc/mfc42.cab">http://activex.microsoft.com/controls/vc
/mfc42.cab</LINK>
; If dependent DLLs are packaged directly into the above cabinet file
; along with an .inf file, specify that .inf file to run as follows:
;InfFile=mfc42.inf
; The mfc42.cab file actually contains a self extracting executable.
; In this case we specify a run= command.
run=%EXTRACT_DIR%\mfc42.exe

; thiscab is a keyword which, in this case, means that test.ocx
; can be found in the same .cab file as this .inf file
; file-win32-x86 is an x86 platform specific identifier
; See the ActiveX SDK - ActiveX Controls - Internet Component Download -
; Packaging component code for automatic download

[test.ocx]
file-win32-x86=thiscab
; *** add your controls CLSID here ***
clsid={0D886696-C7CE-11D3-A175-08002BF17507}
; Add your ocx's file version here.
FileVersion=1,0,0,1
RegisterServer=yes

세미콜론(;) : 주석문을 표시한다.
"[Add.Code]" : 설치할 파일들을 나열한다. inf 내에 등록 하려는 ocx 는 [Add.Code] 섹션 맨 위 제일 위에 적어준다. 설치되는 순서가 중요하다.

"hook"은 설치할 방법을 설정하는 부분의 Title을 입력한다.

"thiscab"은 이 INF를 포함하는 CAB 파일을 의미하는 키워드이다.

"file-win32-x86"에 thiscab 대신 아래와 같이 절대 경로 또는 상대 경로를 지정하여 HTTP 위치에서 필요한 DLL을 다운로드할 수 있다.

file-win32-x86=http://example.microsoft.com/mydir/NEEDED.DLL 


FileVersion은작성한 OCX 파일의 버전을 입력(Resource에서 설정한 값과 같이 입력)한다. 설명상 FileVersion은 ActiveX 파일을 작성하여 배포하던 중 버그를 발견하여 수정하여 재 배포를 할 때 이 파일 버전을 높여 주면 Client에서 알아서 다시 다운로드를 받는다. 버전 표기시 쉼표로 꼭 구분해준다. (제대로 다운로드 되지 않음)

Windows 탐색기에서 마우스 오른쪽 단추로 클릭하여 파일의 버전 번호를 확인할 수 있다.

"DestDir"은 파일을 로드할 디렉터리이며, 11은 WINDOWS/SYSTEM 또는 WINNT/SYSTEM32 시스템 디렉터리를 지정하며, 10은 WINDOWS 또는 WINNT Windows 디렉터리를 지정합니다. 일반적으로 DestDir는 지정하지 않는데, 그런 경우 코드는 고정된 OCCACHE 디렉터리에 설치됩니다.

위의 내용 중 test를 자신이 작성한 ActiveX 컨트롤의 이름으로 변경하고

"clsid"는 설치될 컨트롤의 CLSID입니다.

clsid={0D886696-C7CE-11D3-A175-08002BF17507} 를 자신이 작성한 컨트롤의 clsid로 수정한다.

clsid는 ActiveX 컨트롤을 만든 디렉토리의 .idl 파일을 열어 가장 마지막에 나와 있는 제작한 ActiveX 컨트롤의 id를 입력하면 된다.

CLSID란???
Class Identifier로서 COM 개체를 식별하는데 사용되는 GUID 값이다. 그렇다면 GUID란 또 무엇인가? GUID(Globally Unique Identifier)란 128비트의 크기를 갖는 구조체로서 전세계적으로 시간과 장소에 관계없이 고유하다고 보장할 수 있는 어떤 값을 나타내는 식별자로 사용된다. UUID(Uinversally Unique Identifier)라고도 한다. COM에서 Interface와 개체의 고유성을 보장하기 위해 사용되는 값이라고 알아두자. 더욱 자세한 내용을 알고 싶은 독자는 COM 관련 서적이나 MSDN을 참고하길 하란다.

INF 파일을 만들어서 아래 CAB 파일 생성에 포함시켜야만 배포시 웹페이지에서 ActiveX 다운로드할 때 참조된다.

참조 링크:

CAB 파일 만들기.

Code Sign과 배포

CAB 파일 작성법

3. 디지털 서명(Code Sign)된 CAB 파일 만들기
섹션 편집

ActiveX Control을 만들어서 웹페이지에 올리기 위해서는 반드시 Code Sign을 해야한다.간단히 말해 Code Sign은 보안 문제 때문에 필요한 작업이다.

웹페이지에 올려진 Control은 Client의 시스템에 설치된 후 실행되기 때문에 항상 위험성을 내포하고 있다.

따라서 Internet Explorer는 Control을 다운로드 받을때 Control이 디지털 서명(Digital Signature)을 가지고 있는지를 검사한다.

디지털 서명이란 해당 Control을 제작한 회사를 나타내는 바이트 문자열이다. 또한 Control은 디지털 서명을 확인할 수 있도록 보안증(Certificate)이라고 하는 또 다른 바이트 문자열을 제공해야 한다.

개발기간중에는 임시로 테스트용 디지털 서명을 만들어서 사용할 수 있다.

정식 서비스 배포시에는 유료로 제공되는 인증된 디지털 서명 파일이 필요하다.

CAB 파일 생성과 디지털 서명에 필요한 툴입니다. (첨부파일에 있음)

CabArc.exe: Cabinet Archive(CAB)파일을 생성해 주는 프로그램.
SignCode.exe: CAB 파일을 비밀키와 인증서로 싸인해 줍니다. CAB파일에 코드사인을 합니다.
ChkTrust.exe: 코드사인 작업이 잘 수행되었는가 검증해 주는 프로그램 입니다.
MakeCert.exe: 테스트용 인증서를 만들어 주는 프로그램 입니다.
Cert2Spc.exe: MakeCert로 만들어진 시험용 인증서를 사인하는 작업에 사용될 수 있도록 변환하는 프로그램.

  1. 배포에 필요한 CAB 파일 생성
    • CABARC -s 6144 n MYCTL.CAB NEEDED1.DLL NEEDED2.DLL MYCTL.OCX MYCTL.INF
    • CABARC는 MYCTL.CAB라는 CAB 파일을 만듭니다.
    • 소스 파일(INF, OCX 및 DLL 파일)이 들어 있는 디렉터리에서 CABARC를 실행해야 한다.
    • CAB 파일에 보관될 파일은 INF 파일에 나열된 순서대로 명령줄에 나열되어야 한다.
    • 위 예제의 INF 파일에서는 NEEDED1.DLL, NEEDED2.DLL, MYCTL.OCX의 순서로 나열되어야 한다.
    • -s 옵션은 캐비닛에코드 서명을 위한 공간을 예약한다. n 명령은 CAB 파일을 만든다는 것을 지정한다.
    • 라인 맨 뒤에 INF 파일은 위에서 CAB 파일을 위해 수동으로 만들어진 .inf 파일이다.
  2. 디지털 서명 (테스트) 파일 만들기 (유료 인증된 디지털 서명 파일이 있을 경우 테스트용으로 만들 필요 없음)
    • makecert -n "CN=MySoftwareCompany" -sv MyKey.pvk MyCert.cer
    • pvk 라는 개인 키 파일과 .cer 라는 회사 인증서 파일을 테스트용으로 만든다.
    • 생성시 개인 키 암호를 물어보는데 아무거나 설정하면 되면 나중에 CAB파일에 코드 사인할때 입력해야 한다.
  3. 디지털 서명 cer 파일로 spc 파일 만들기
    • cert2spc MyCert.cer MyCert.spc
    • 테스트를 위한 SPC(소프트웨어 게시 인증서)를 만든다.
  4. CAB 파일에 디지털 서명 파일로 코드사인하기
    • signcode -v MyKey.pvk -spc MyCert.spc MYCTL.CAB
    • 개인 키 암호 입력 대화 상자가 생성되고 위 과정에서 입력한 암호를 입력하면 .cab 파일에 디지털 서명한다.
  5. 테스트 디지털 서명이 인식되도록 클라이언트 시스템에 설정하기 (한번만 하면 됨)
    • SETREG 1 TRUE
    • 해당 클라이언트에서 보증 확인 과정을 제어하는 레지스트리 키를 설정하는 것이다.
  6. 디지털 서명된 CAB 파일 이상없는지 확인하기
    • chktrust MYCTL.CAB

(MSDN) 다음은 서명된 CAB 파일을 만드는 단계입니다.

  1. Software Publisher Certificate 얻기(한 번만 수행하면 됨)
  2. CAB 파일 만들기.
  3. CAB 파일 서명.
  4. 웹 페이지에 서명된 CAB 파일 포함(선택적)

참조 링크:

MFC 및 ATL 컨트롤을 위한 서명된 CAB 파일 만들기

Code Sign과 배포

CAB 파일 작성법

배포하기(Cab 파일 작성법)

signcode.exe 사용법 : DOS 버전
signcode.exe 사용법 : 윈도우 버전

cabarc.exe사용법 : CAB화일 제작

테스트용 디지털 서명된 ActiveX 실행할 때 보안 설정

정식 디지털 서명되지 않고 테스트 서명된 ActiveX는 보통 이상으로 보안 설정된 일반 유저의 IE에서는 보안상 실행되지 않는다.

임시 테스트를 하기 위해선 아래와 같은 방법이 있으며 유저들에게 정식으로 배포하기 위해서 공인된 디지털 서명 제공 업체에서 유료로 결제 후에 공인된 디지털 서명을 받아서 배포해야만 한다.

  • 인터넷 옵션의 보안 - 보안 수준 에서 보안 설정을 최하로 변경한다. (서명되지 않은 ActiveX도 다운로드 허용된다.)
  • 인터넷 옵션의 보안 - 신뢰할 수 있는 사이트 - 사이트 에서 해당 사이트를 신뢰하는 사이트로 설정한다.
  • 인터넷 옵션의 보안 - 사용자 지정 수준 - 보안 설정 에서 "서명 안 된 ActiveX 컨트롤 다운로드" "사용 안 함"에서 "확인"으로 변경해야 한다. 일반적으로 기본은 "사용 안 함 (권장)"으로 설정되어 있다.

인증된 디지털 서명 유료 구매하기

디저털 서명은 디지털 서명을 다루는 공인 기관에서 유료로 발급할 수 있다.

  • VeriSign CodeSign : 해외 인증기관. 해외에서 가장 높은 브랜드 : 1년 440000원 / 2년 850000원
  • Thawte CodeSign : 국내에서 가장 많이 사용. 비교적 저렴한 가격 : 1년 180000원 / 2년 320000원
  • Trust CodeSign : 상당히 저렴한 가격 1년 150000원 / 2년 280000원
  • YesSign CodeSign : 금융결제원에서 제공하며 금융관련에서 주로 사용 : 1년 150000원 / 2년 280000원

인증된 디지털 서명 업체

써트 코리아

애니써트

디지털 서명 가이드

자세한 인증서 가이드

4. 웹페이지에 CAB 파일 추가
섹션 편집

ATL 및 MFC 컨트롤은 <OBJECT> 태그를 사용하여 웹 페이지에 포함됩니다. <OBJECT> 태그 안에는 다음과 같은 컨트롤의 세 가지 특성을 지정해야 합니다.

HTML 파일에서 아래와 같이 ActiveX 컨트롤을 끼워 넣는다.

<OBJECT ID="PolyCtl"

CLASSID="CLSID:4CBBC676-507F-11D0-B98B-000000000000"

CODEBASE="http://example.microsoft.com/mydir/polygon.cab">

</OBJECT>

  • ID 컨트롤의 이름
  • CLASSID 컨트롤의 CLSID (위에서 INF 설정시 ActiveX 컨트롤의 CLSID 값과 동일)
  • CODEBASE 컨트롤을 다운로드할 위치. CODEBASE는 다양한 파일 형식을 가리킬 수 있습니다.

CODEBASE는 다음과 같이 OCX 또는 DLL 파일을 직접 지정할 수 있습니다.

CODEBASE="http://example.microsoft.com/mydir/polygon.dll#version=1,0,0,1"

이렇게 하면 DLL 또는 OCX 파일만 다운로드하여 설치하기 때문에 필요한 모든 지원 DLL이 클라이언트 컴퓨터에 있어야 합니다.

CAB 파일에 선택적인 버전 번호를 포함시킬 경우, 해당 버전 번호는 다운로드될 컨트롤을 참조해야 합니다. 예를 들어, POLYGON.DLL의 버전 번호가 1, 0, 0, 1이므로 캐비닛의 버전 역시 1, 0, 0, 1입니다.

CODEBASE="http://example.microsoft.com/mydir/polygon.cab#version=1,0,0,1"

버전 번호를 포함시키지 않을 경우, 동일한 컨트롤의 이전 버전이 클라이언트 컴퓨터에 있어도 새 버전으로 바뀌지 않습니다.

참조 링크:

웹 페이지에 서명된 CAB 파일 포함 (MSDN)

기존 ActiveX 컨트롤 업그레이드 (MSDN)

5. 문제가 생길 경우
섹션 편집

* ActiveX 제작 및 배포 시 참고 및 주의 사항들
- "DestDir은(는) Windows 디렉토리인 경우 10, WindowsSystem(32)인 경우 11이며, Occache 디렉토리인 경우 비워둡니다."

inf 안에 적어주는 배포 되는 파일의 위치입니다.
예)
[test.exe]
file-win32-x86=thiscab
FileVersion=1,0,0,1
DestDir=11

- inf 내에 등록 하려는 ocx 는 [Add.Code] 섹션 맨 위 제일 위에 적어준다.
- 버전 표기 시 쉼표로 꼭 구분해준다. -> 제대로 다운로드 되지 않음
예)
- inf 내 버전 표기 : 2005,4,12,1
- html 페이지 내 : codebase="npos.cab#version=2005,4,21,1"
- 모든 파일이 제대로 다운로드 되었는지 확인해보세요. 가끔 파일이 중간에 다운로드 받다가 다 받지 않은채 손상이 되는 경우가 있더군요.
- 익스플로러 도구-옵션-임시 인터넷 파일-저장된 페이지의 새버전 확인을 페이지를 열 때 마다로 해서 캐쉬 되어 있는 기존 파일을
참조하지 않도록 해주세요.
- 가끔 보니까 downloaded program files 에서 해당 ocx 를 지워도 지워지지 않는 경우가 있는데
regsvr32.exe 로 해제를 해주고 다시 다운로드 받아서 테스트하니 잘 되더군요.

- 그리고 ocx 내부에서 파일을 참조하거나 할 때 예외(파일이 없거나 파일 생성, 삭제 시 예외 발생)가 발생하면 익스플로러가 죽더군요.

- MSDN 에서 본 내용인데 cab 을 묶으실 때 [Add.Code] 내에 놓여져 있는 파일 순서대로 묶어주셔야 한다는겁니다. 아래는 MSDN 원문입니다.

You should run CABARC in the directory that contains your source files (the INF, OCX, and DLL files). The files to be archived in the CAB file should be listed on the command line in the same order they are listed in the INF file. In the example above, the INF file should list NEEDED1.DLL first, then NEEDED2.DLL, and then MYCTL.OCX.

- INF 파일목록에 [Add.Code] 나열된 순서대로 처리를 하지만, 파일들의 설치는 목록의 역순으로 실행된다. 보통 메인 OCX를 파일목록의 첫번째에 두고 참조dll을 그뒤에 두는데, 이것은 메인OCX의 등록시점에 참조dll들의 설치완료를 보장하기위한 것이다.

출처:INF파일

ActiveX 컨트롤이 웹페이지에서 정상적으로 다운로드 안될 경우 로그 보는법 (MSDN)

Code Down Load Log Viewer (cdllogvw.exe) 파일 다운로드

+ Recent posts