bool CDSObject::FilterContains(const FilterMap &filter, const QString& name) const { // ContentDirectory Service, 2013 UPnP Forum // 2.3.18 A_ARG_TYPE_Filter // Exact match if (filter.contains(name, Qt::CaseInsensitive)) return true; // # signfies that this property and all it's children must be returned // This is presently implemented higher up to save time // If an attribute is required then it's parent must also be returned QString dependentAttribute = QString("%1@").arg(name); QStringList matches = filter.filter(name, Qt::CaseInsensitive); QStringList::iterator it; for (it = matches.begin(); it != matches.end(); ++it) { if ((*it).startsWith(dependentAttribute)) return true; } return false; }
void CDSObject::toXml( QTextStream &os, FilterMap &filter, bool ignoreChildren ) const { QString sEndTag = ""; /** * NOTE FilterMap contains a list of what should be included, not what should * be excluded. * * The client is expected either to indicate that everything should be * returned with an asterix, or to supply a comma seperated list of * the only the named properties and attributes. * * @ - Attributes are denoted by format <element>@<attribute> * * # - The use of a hash at the end of a name indicates that this * property and all it's children and attributes should be returned. * * Inclusion of an attribute in the filter list implies the inclusion * of it's parent element and value. * e.g. filter="res@size" implies <res size="{size}">{url}</res> * However optional tags such as res@duration which are not named will * be omitted. * * 'Required' properties must always be included irrespective of * any filter! * * See UPnP MediaServer, ContentDirectory Service Section 2.3.18, 2013 */ bool bFilter = true; if (filter.contains("*")) bFilter = false; switch( m_eType ) { case OT_Container: { if (bFilter && filter.contains("container#")) bFilter = false; os << "<container id=\"" << m_sId << "\" parentID=\"" << m_sParentId << "\" restricted=\"" << GetBool( m_bRestricted ); if (!bFilter || filter.contains("@searchable")) os << "\" searchable=\"" << GetBool( m_bSearchable ); if (!bFilter || filter.contains("@childCount")) os << "\" childCount=\"" << GetChildCount(); if (!bFilter || filter.contains("@childContainerCount")) os << "\" childContainerCount=\"" << GetChildContainerCount(); os << "\" >" << endl; sEndTag = "</container>"; break; } case OT_Item: { if (bFilter && filter.contains("item#")) bFilter = false; os << "<item id=\"" << m_sId << "\" parentID=\"" << m_sParentId << "\" restricted=\"" << GetBool( m_bRestricted ) << "\" >" << endl; sEndTag = "</item>"; break; } default: break; } os << "<dc:title>" << m_sTitle << "</dc:title>" << endl; os << "<upnp:class>" << m_sClass << "</upnp:class>" << endl; // ---------------------------------------------------------------------- // Output all Properties // ---------------------------------------------------------------------- Properties::const_iterator it = m_properties.begin(); for (; it != m_properties.end(); ++it) { const Property *pProp = *it; if (pProp->m_bRequired || (!pProp->GetValue().isEmpty())) { QString sName; if (!pProp->m_sNameSpace.isEmpty()) sName = pProp->m_sNameSpace + ':' + pProp->m_sName; else sName = pProp->m_sName; if (pProp->m_bRequired || (!bFilter) || FilterContains(filter, sName)) { bool filterAttributes = true; if (!bFilter || filter.contains(QString("%1#").arg(sName))) filterAttributes = false; os << "<" << sName; NameValues::const_iterator nit = pProp->m_lstAttributes.begin(); for (; nit != pProp->m_lstAttributes.end(); ++ nit) { QString filterName = QString("%1@%2").arg(sName) .arg((*nit).m_sName); if ((*nit).m_bRequired || !filterAttributes || filter.contains(filterName)) os << " " << (*nit).m_sName << "=\"" << (*nit).m_sValue << "\""; } os << ">"; os << pProp->GetEncodedValue(); os << "</" << sName << ">" << endl; } } } // ---------------------------------------------------------------------- // Output any Res Elements // ---------------------------------------------------------------------- if (!bFilter || filter.contains("res")) { bool filterAttributes = true; if (!bFilter || filter.contains("res#")) filterAttributes = false; Resources::const_iterator rit = m_resources.begin(); for (; rit != m_resources.end(); ++rit) { os << "<res protocolInfo=\"" << (*rit)->m_sProtocolInfo << "\" "; QString filterName; NameValues::const_iterator nit = (*rit)->m_lstAttributes.begin(); for (; nit != (*rit)->m_lstAttributes.end(); ++ nit) { filterName = QString("res@%1").arg((*nit).m_sName); if ((*nit).m_bRequired || !filterAttributes || filter.contains(filterName)) os << (*nit).m_sName << "=\"" << (*nit).m_sValue << "\" "; } os << ">" << (*rit)->m_sURI; os << "</res>" << endl; } } // ---------------------------------------------------------------------- // Output any children // ---------------------------------------------------------------------- if (!ignoreChildren) { CDSObjects::const_iterator cit = m_children.begin(); for (; cit != m_children.end(); ++cit) (*cit)->toXml(os, filter); } // ---------------------------------------------------------------------- // Close Element Tag // ---------------------------------------------------------------------- os << sEndTag << endl; os << flush; }