/////////////////////////////////////////////////////////////////////////////////
//////// int ParseDoc(IHTMLDocument2 *, LPTSTR *) : 도큐먼트 파싱
/////////////////////////////////////////////////////////////////////////////////
// 인수 1: [in] IHTMLDocument2 인터페이스 포인터
// 인수 2: [out] LPTSTR의 포인터
// 리턴값: [ret] 다큐먼트내 프레임의 수(에러면 0, 정상리턴이면 1이상의 값)
// 주의) 리턴 후 caller 측에서 두번째 인수 널값이 아니면 free로 반드시 해제
/////////////////////////////////////////////////////////////////////////////////
/* 사용법 샘플)
LPTSTR lpszParsed;
int iCount=ParseDoc(m_pDoc, &lpszParsed);
if(iCount){
...
...
...
free(lpszParsed);
} else {
... // 에러일 경우 처리
}
*/
/////////////////////////////////////////////////////////////////////////////////
int ParseDoc(IHTMLDocument2 * pDoc, LPTSTR * ppszParsed);
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
int ParseDocRecur(IHTMLDocument2 * pDoc, LPTSTR * ppszParsed);
int ParseDoc(IHTMLDocument2 * pDoc, LPTSTR * ppszParsed){
if(pDoc ==0 || ppszParsed==0){ // 전달 인수 간단한 유효성 검사: 기본적 에러 처리
MessageBox(NULL, _T("Parameter is invalid - ParseDoc"), _T("error"), MB_ICONERROR);
return 0;
}
*ppszParsed = 0; // 초기화
return ParseDocRecur(pDoc, ppszParsed);
}
int ParseDocRecur(IHTMLDocument2 * pDoc, LPTSTR * ppszParsed){
LPTSTR p = *ppszParsed;
int iFrameCount=0;
BSTR bstrSource;
HRESULT hr=pDoc->get_URL(&bstrSource);
if(FAILED(hr)){MessageBox(NULL, _T("IHTMLDocument2::get_URL failed. - ParseDocReCur"), _T("error"), MB_ICONERROR); return 0;}
#if defined(UNICODE) || defined(_UNICODE)
int iLen=lstrlen(p);
int iTargetLen=lstrlen(bstrSource);
p=(LPTSTR)realloc(p, (iLen+iTargetLen+5)*sizeof(TCHAR));
lstrcpy(p+iLen, bstrSource);
lstrcat(p,_T("\r\n\r\n"));
iLen += iTargetLen+4;
#else
int iNeedSize=WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,bstrSource,-1,0,0,0,0);
int iLen=lstrlen(p);
p=(LPTSTR)realloc(p, iLen+iNeedSize+4); // 참고) iNeedSize는 이미 널 포함된 길이값이다.
if(NULL == p){MessageBox(NULL, _T("realloc failed. - ParseDocReCur"), _T("error"), MB_ICONERROR); return 0;}
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,bstrSource,-1,p+iLen,iNeedSize,0,0);
lstrcat(p, _T("\r\n\r\n")); // 2번 개행
iLen += iNeedSize+4-1; // iNeedSize에 널이 포함되었으므로 1을 빼준다.
#endif
SysFreeString(bstrSource);
//*ppszParsed = p;
IHTMLElement * pBodyEl=0, * pParentEl=0;
hr=pDoc->get_body(&pBodyEl);
if(FAILED(hr) || pBodyEl==0){MessageBox(NULL, _T("IHTMLDocument2::get_body failed. - ParseDocRecur"), _T("error"), MB_ICONERROR); return 0;}
hr=pBodyEl->get_parentElement(&pParentEl);
if(FAILED(hr) || pParentEl==0){MessageBox(NULL, _T("IHTMLDocument2::get_parentElement failed. - ParseDocRecur"), _T("error"), MB_ICONERROR); return 0;}
pBodyEl->Release();
hr=pParentEl->get_outerHTML(&bstrSource);
if(FAILED(hr)){MessageBox(NULL, _T("IHTMLDocument2::get_outerHTML failed. - ParseDocRecur"), _T("error"), MB_ICONERROR); return 0;}
pParentEl->Release();
#if defined(UNICODE) || defined(_UNICODE)
iTargetLen=lstrlen(bstrSource);
p=(LPTSTR)realloc(p, (iLen+iTargetLen+5)*sizeof(TCHAR)); // 개행+널 고려 5를 더해줌
lstrcpy(p+iLen, bstrSource);
lstrcat(p,_T("\r\n\r\n"));
iLen += iTargetLen+4;
#else
iNeedSize=WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,bstrSource,-1,0,0,0,0);
p=(LPTSTR)realloc(p, iLen+iNeedSize+4);
if(!p){MessageBox(NULL, _T("realloc failed. - ParseDocRecur"), _T("error"), MB_ICONERROR); return 0;}
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,bstrSource,-1,p+iLen,iNeedSize,0,0);
lstrcat(p, _T("\r\n\r\n"));
iLen += iNeedSize+4-1;
#endif
SysFreeString(bstrSource);
*ppszParsed = p; // 리얼록으로 할당주소 변경되었으므로 반영해 준다.
iFrameCount++;
// 프레임의 수를 검사하고 그 수만큼 재귀루프를 돌린다.(프레임 안에 또 프레임이 존재 가능)
IHTMLFramesCollection2 * pFrameCol=0;
hr=pDoc->get_frames(&pFrameCol);
if(FAILED(hr) || pFrameCol==0){MessageBox(NULL, _T("IHTMLFramesCollection2::get_frames failed. - ParseDocRecur"), _T("error"), MB_ICONERROR); return 0;}
long lFrameElCount=0;
pFrameCol->get_length(&lFrameElCount);
if(FAILED(hr)){MessageBox(NULL, _T("IHTMLFramesCollection2::get_length failed. - ParseDocRecur"), _T("error"), MB_ICONERROR); return 0;}
VARIANT varIndex, varResult;
varIndex.vt=VT_I4;
long i;
for(i=0; i<lFrameElCount ;i++){
varIndex.lVal=i;
hr=pFrameCol->item(&varIndex, &varResult);
if(FAILED(hr)) continue;
IHTMLWindow2 * pWin=0;
hr=varResult.pdispVal->QueryInterface(IID_IHTMLWindow2, (void**)&pWin);
if(FAILED(hr) || pWin==0) continue;
varResult.pdispVal->Release();
IHTMLDocument2 * pSubDoc=0;
hr=pWin->get_document(&pSubDoc);
if(FAILED(hr) || pSubDoc==0) continue;
pWin->Release();
iFrameCount += ParseDocRecur(pSubDoc, ppszParsed);
pSubDoc->Release();
}
pFrameCol->Release();
return iFrameCount;
}
'웹, HTML' 카테고리의 다른 글
IE 내부에 나타나는 팝업메뉴에 추가 - 참조만... 자세하지 않다. (2) | 2008.09.18 |
---|---|
HTMLDocumentEvents2 Dispinterface - 다큐먼트 이벤트 아이디 기타 등등 참조 (0) | 2008.09.17 |
웹페이지 로딩 완료 시점 파악하기 - 멀티 프레임시 고려사항 주의 (1) | 2008.09.17 |
WalkAll 코드 - 모니커 이용 UI 없는 다큐먼트 로딩 IPropertyNotifySink 구현 부분 참조 (2) | 2008.09.16 |
About the Browser - 웹브라우저에 대한 전반적인 아키텍쳐 (0) | 2008.09.16 |
어떻게 URL 모니커를 사용해서 데이터를 post하는가? (1) | 2008.09.15 |
URL Monikers and OLE Hyperlinks - 좋은 개념글 (1) | 2008.09.15 |