template<typename Char> struct CaseInsensitiveCompare {
public:
bool operator()(Char x, Char y) const {
return tolower(x) == tolower(y);
}
};
std::wstring GetFaviconUrlFromDocument(IHTMLDocument2* doc2)
{
if (!doc2)
{
return std::wstring();
}
static std::wstring const linktag = L"LINK";
CComPtr<IHTMLElementCollection> ielemCol;
CComPtr<IHTMLLinkElement> lnkelem;
if (FAILED(doc2->get_all(&ielemCol)))
{
return std::wstring();
}
CComPtr<IDispatch> displink;
CComQIPtr<IHTMLElement, &IID_IHTMLElement> ielem;
if (FAILED(ielemCol->tags(CComVariant(linktag), &displink)))
{
return std::wstring();
}
if (FAILED(displink->QueryInterface(IID_IHTMLElementCollection, (void**)&ielemCol)))
{
return std::wstring();
}
long count = 0;
if (FAILED(ielemCol->get_length(&count)))
{
return std::wstring();
}
CComPtr<IDispatch> dispEnum;
for (long i=0; i<count; i++)
{
CComVariant index = i;
if (SUCCEEDED(ielemCol->item(index, index, &dispEnum)))
{
ielem = dispEnum;
CComBSTR bstr;
if (SUCCEEDED(ielem->get_tagName(&bstr)))
{
std::wstring tag = bstr;
if (tag.length() == linktag.length() &&
std::equal(tag.begin(), tag.end(), linktag.begin(), CaseInsensitiveCompare<wchar_t>()))
{
if(SUCCEEDED(ielem->QueryInterface(IID_IHTMLLinkElement, (void**)&lnkelem)) && lnkelem)
{
if(SUCCEEDED(lnkelem->get_rel(&bstr)))
{
std::wstring rel = bstr;
std::wstring shortcut_icon(L"shortcut icon");
if (rel.length() == shortcut_icon.length() &&
std::equal(rel.begin(), rel.end(), shortcut_icon.begin(), CaseInsensitiveCompare<wchar_t>()))
{
if(SUCCEEDED(lnkelem->get_href(&bstr)))
{
std::wstring url = bstr;
return url;
}
}
}
}
}
}
}
}
return std::wstring();
}
}