📄 devicedescriptionparsing.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
#include "pch.h"
#pragma hdrstop
#include "variant.h"
#include "HttpRequest.h"
#include "upnp_config.h"
#include "DeviceDescription.h"
#include "Device.h"
static wchar_t pwszRootElement[] =
L"<urn:schemas-upnp-org:device-1-0>"
L"<root>";
static wchar_t pwszSpecVersionMajorElement[] =
L"<urn:schemas-upnp-org:device-1-0>"
L"<root>"
L"<urn:schemas-upnp-org:device-1-0>"
L"<specVersion>"
L"<urn:schemas-upnp-org:device-1-0>"
L"<major>";
static wchar_t pwszSpecVersionMinorElement[] =
L"<urn:schemas-upnp-org:device-1-0>"
L"<root>"
L"<urn:schemas-upnp-org:device-1-0>"
L"<specVersion>"
L"<urn:schemas-upnp-org:device-1-0>"
L"<minor>";
static wchar_t pwszDeviceElement[] =
L"<urn:schemas-upnp-org:device-1-0>"
L"<root>"
L"<urn:schemas-upnp-org:device-1-0>"
L"<device>";
static wchar_t pwszURLBaseElement[] =
L"<urn:schemas-upnp-org:device-1-0>"
L"<root>"
L"<urn:schemas-upnp-org:device-1-0>"
L"<URLBase>";
// Parse
HRESULT DeviceDescription::Parse(LPCSTR pszDescriptionURL)
{
// download device description
HttpRequest request;
HRESULT hr = E_FAIL;
if(!request.Open("GET", pszDescriptionURL))
return E_FAIL; // TO DO: error
if(!request.Send())
{
TraceTag(ttidError, "DeviceDescription: Error sending request for device description: 0x%08x", request.GetHresult());
return request.GetHresult();
}
if(HTTP_STATUS_OK != request.GetStatus())
{
TraceTag(ttidError, "DeviceDescription: Error getting device description: %d", request.GetStatus());
return E_FAIL; // TO DO: error
}
ce::SequentialStream<HttpRequest> Stream(request, upnp_config::max_document_size());
ce::SAXReader Reader;
if(Reader.valid())
{
ce::variant v;
Stream.QueryInterface(IID_ISequentialStream, (void**)&v.punkVal);
v.vt = VT_UNKNOWN;
Reader->putContentHandler(this);
hr = Reader->parse(v);
if(FAILED(hr))
TraceTag(ttidError, "SAXXMLReader::parse returned error 0x%08x", hr);
}
else
hr = Reader.Error();
// verify version
if(SUCCEEDED(hr) && (m_strSpecVersionMajor != L"1" || m_strSpecVersionMinor != L"0"))
{
TraceTag(ttidError, "DeviceDescription: Invalid document version");
hr = E_FAIL;
}
if(SUCCEEDED(hr))
{
if(!m_strBaseURLTag.empty())
// use the value from URLBase tag
ce::WideCharToMultiByte(CP_UTF8, m_strBaseURLTag, -1, &m_strBaseURL);
else
// use location of device description file as the base URL
m_strBaseURL = pszDescriptionURL;
// fix relative URLs
for(ce::list<Device*>::iterator it = m_listDevices.begin(), itEnd = m_listDevices.end(); it != itEnd; ++it)
(*it)->FixDeviceURL();
}
return hr;
}
// DeviceAddedCallback
void DeviceDescription::DeviceAddedCallback(Device* pDevice)
{
m_listDevices.push_back(pDevice);
}
// startElement
HRESULT STDMETHODCALLTYPE DeviceDescription::startElement(
/* [in] */ const wchar_t __RPC_FAR *pwchNamespaceUri,
/* [in] */ int cchNamespaceUri,
/* [in] */ const wchar_t __RPC_FAR *pwchLocalName,
/* [in] */ int cchLocalName,
/* [in] */ const wchar_t __RPC_FAR *pwchQName,
/* [in] */ int cchQName,
/* [in] */ ISAXAttributes __RPC_FAR *pAttributes)
{
SAXContentHandler::startElement(pwchNamespaceUri, cchNamespaceUri, pwchLocalName, cchLocalName, pwchQName, cchQName, pAttributes);
if(m_bAbort)
return E_ABORT;
if(!m_bParsedRootElement)
{
// this is root element of the document
m_bParsedRootElement = true;
// immediately terminate parsing/downloading if root element is not valid for UPnP device description
if(pwszRootElement != m_strFullElementName)
{
TraceTag(ttidError, "DeviceDescription: Invalid root element");
return E_FAIL;
}
}
if(m_pTempDevice)
m_pTempDevice->startElement(pwchNamespaceUri, cchNamespaceUri, pwchLocalName, cchLocalName, pwchQName, cchQName, pAttributes);
else
// Device element
if(pwszDeviceElement == m_strFullElementName)
{
// start of root device
// this section will be parsed by new device object
m_pTempDevice = new Device(this);
if(!m_pTempDevice)
return ERROR_OUTOFMEMORY;
// simulate startDocument for the device
m_pTempDevice->startDocument();
}
return S_OK;
}
// endElement
HRESULT STDMETHODCALLTYPE DeviceDescription::endElement(
/* [in] */ const wchar_t __RPC_FAR *pwchNamespaceUri,
/* [in] */ int cchNamespaceUri,
/* [in] */ const wchar_t __RPC_FAR *pwchLocalName,
/* [in] */ int cchLocalName,
/* [in] */ const wchar_t __RPC_FAR *pwchQName,
/* [in] */ int cchQName)
{
if(m_bAbort)
return E_ABORT;
// URLBase
if(pwszURLBaseElement == m_strFullElementName)
m_strBaseURLTag.trim(L"\n\r\t ");
// specVersion major
if(pwszSpecVersionMajorElement == m_strFullElementName)
{
m_strSpecVersionMajor.trim(L"\n\r\t ");
if(m_strSpecVersionMajor != L"1")
{
TraceTag(ttidError, "DeviceDescription: Invalid document version");
return E_FAIL;
}
}
// specVersion minor
if(pwszSpecVersionMinorElement == m_strFullElementName)
{
m_strSpecVersionMinor.trim(L"\n\r\t ");
if(m_strSpecVersionMinor != L"0")
{
TraceTag(ttidError, "DeviceDescription: Invalid document version");
return E_FAIL;
}
}
// Device element
if(pwszDeviceElement == m_strFullElementName)
{
Assert(m_pTempDevice);
// finished parsing root device;
// simulate endDocument
m_pTempDevice->endDocument();
Assert(m_pRootDevice == NULL);
m_pRootDevice = m_pTempDevice;
m_pTempDevice = NULL;
}
if(m_pTempDevice)
m_pTempDevice->endElement(pwchNamespaceUri, cchNamespaceUri, pwchLocalName, cchLocalName, pwchQName, cchQName);
return SAXContentHandler::endElement(pwchNamespaceUri, cchNamespaceUri, pwchLocalName, cchLocalName, pwchQName, cchQName);
}
// characters
HRESULT STDMETHODCALLTYPE DeviceDescription::characters(
/* [in] */ const wchar_t __RPC_FAR *pwchChars,
/* [in] */ int cchChars)
{
if(m_bAbort)
return E_ABORT;
// URLBase
if(pwszURLBaseElement == m_strFullElementName)
m_strBaseURLTag.append(pwchChars, cchChars);
// specVersion major
if(pwszSpecVersionMajorElement == m_strFullElementName)
m_strSpecVersionMajor.append(pwchChars, cchChars);
// specVersion minor
if(pwszSpecVersionMinorElement == m_strFullElementName)
m_strSpecVersionMinor.append(pwchChars, cchChars);
if(m_pTempDevice)
m_pTempDevice->characters(pwchChars, cchChars);
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -