UtlBoolean SipPublishContentMgr::getContent(const char* resourceId, const char* eventTypeKey, const char* eventType, UtlBoolean fullState, const UtlString& acceptHeaderValue, HttpBody*& content, UtlBoolean& isDefaultContent, UtlString* availableMediaTypes) { UtlBoolean foundContent = FALSE; PublishContentContainer* container = NULL; isDefaultContent = FALSE; UtlString key; key.append(resourceId); key.append(CONTENT_KEY_SEPARATOR); key.append(eventTypeKey); lock(); UtlHashBag* pContent; if (fullState) { // Full content (this is the usual case) pContent = &mContentEntries; } else { // Partial content (used for partial dialog events) pContent = &mPartialContentEntries; } // See if resource-specific content exists container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // There is no resource-specific content. Check if the default // constructor exists. if (container == NULL) { // Construct the key for the default data. UtlString default_key; default_key.append(CONTENT_KEY_SEPARATOR); default_key.append(eventTypeKey); // Look up the constructor. UtlHashMap* pDefaultConstructors; if (fullState) { // Full content (this is the usual case) pDefaultConstructors = &mDefaultContentConstructors; } else { // Partial content (used for partial dialog events) pDefaultConstructors = &mDefaultPartialContentConstructors; } SipPublishContentMgrDefaultConstructor* constructor = dynamic_cast <SipPublishContentMgrDefaultConstructor*> (pDefaultConstructors->findValue(&default_key)); // If it exists, call it to publish content for this resource/event. if (constructor) { constructor->generateDefaultContent(this, resourceId, eventTypeKey, eventType); } // See if resource-specific content exists now. container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // If content was found, still mark it as default content. if (container) { isDefaultContent = TRUE; } // If still no content was found, check if (fixed) default content exists. else { container = dynamic_cast <PublishContentContainer*> (mDefaultContentEntries.find(&default_key)); if(container) { isDefaultContent = TRUE; } } } // Within the container, choose the correct content. if (container) { if (acceptHeaderValue.compareTo(acceptAllTypes) != 0) { // Search for the first content in the container whose // MIME type is in the acceptable list. UtlSListIterator contentIterator(container->mEventContent); HttpBody* bodyPtr; while (!foundContent && (bodyPtr = dynamic_cast <HttpBody*> (contentIterator()))) { // Trim any parameters off the body content type. UtlString* content_type = bodyPtr; UtlString base_content_type(*content_type); ssize_t i = base_content_type.index(';'); if (i != UTL_NOT_FOUND) { base_content_type.remove(i); } // See if base_content_type is in acceptHeaderValue. if (acceptHeaderValue.findToken(base_content_type.data(), ",", ";")) { // If base_content_type is "multipart/related", extract // the 'type' parameter value, which is the type of the // root component, and check whether it is in acceptHeaderValue. ssize_t j; if (base_content_type.compareTo("multipart/related", UtlString::ignoreCase) == 0) { // Search for the 'type' parameter. i = content_type->index(";type=", UtlString::ignoreCase); if (i != UTL_NOT_FOUND) { // Advance i to point to the value. i += sizeof (";type=") - 1; if ((*content_type)(i) == '\"') { // Value is quoted. // Advance i to point to the value proper. i++; // Find the closing double-quote. j = content_type->index('\"', i); if (j == UTL_NOT_FOUND) { // This shouldn't happen. Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent " "No closing double-quote found for 'type' parameter in body MIME type '%s'", content_type->data()); // j == UTL_NOT_FOUND indicates failure. } } else { // Value is not quoted. // Find the end of the parameter. j = content_type->index(';', i); if (j == UTL_NOT_FOUND) { j = content_type->length(); } } if (j != UTL_NOT_FOUND) { // Characters from i to j are the type parameter value. UtlString base_root_type; base_root_type.append(*content_type, i, j - i); // Remove parameters from base_root_type. ssize_t k = base_content_type.index(';'); if (k != UTL_NOT_FOUND) { base_content_type.remove(k); } // See if base_root_type is in acceptHeaderValue. if (acceptHeaderValue.findToken(base_root_type.data(), ",", ";")) { // Having passed all the tests, this content is OK. foundContent = true; } } } else { Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent " "No 'type' parameter in body MIME type '%s'", content_type->data()); } } else { // If base_content_type is not multipart/related, // we can accept the content with no further tests. foundContent = true; } // If this content is acceptable, copy it into 'content'. // Because foundContent is true, the loop will exit. if (foundContent) { content = bodyPtr->copy(); } } } if (!foundContent) { // No content was found that matched the allowed MIME types. Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no acceptable content found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s'", key.data(), acceptHeaderValue.data(), resourceId ? resourceId : "[none]", eventTypeKey, eventType); if (availableMediaTypes) { // Construct the list of available MIME types. availableMediaTypes->remove(0); contentIterator.reset(); while ((bodyPtr = dynamic_cast <HttpBody*> (contentIterator()))) { if (!availableMediaTypes->isNull()) { availableMediaTypes->append(','); } availableMediaTypes->append(static_cast <UtlString&> (*bodyPtr)); } } } } else { // No MIME types were specified, take the first content in the list. // (which should exist) HttpBody* bodyPtr = dynamic_cast <HttpBody*> (container->mEventContent.first()); if (bodyPtr) { content = bodyPtr->copy(); foundContent = TRUE; } else { // No content was found (at all). // Set *availableMediaTypes. if (availableMediaTypes) { availableMediaTypes->remove(0); } Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no content found for key '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s' - publish() must have been called with numContentTypes==0", key.data(), resourceId ? resourceId : "[none]", eventTypeKey, eventType); } } } else { // No container found for this resource and event. // Set *availableMediaTypes. if (availableMediaTypes) { availableMediaTypes->remove(0); } Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no container found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s', fullState = %d", key.data(), acceptHeaderValue.data(), resourceId ? resourceId : "[none]", eventTypeKey, eventType, fullState); } unlock(); return foundContent; }
UtlBoolean SipPublishContentMgr::getContent(const char* resourceId, const char* eventTypeKey, const char* eventType, const char* acceptHeaderValue, HttpBody*& content, int& version, UtlBoolean& isDefaultContent, UtlBoolean fullState) { UtlBoolean foundContent = FALSE; UtlString key(resourceId); key.append(eventTypeKey); PublishContentContainer* container = NULL; isDefaultContent = FALSE; // Turn acceptHeaderValue into a HashBag of its components. // acceptedTypesGiven = FALSE if there are no components. UtlHashBag contentTypes; UtlBoolean acceptedTypesGiven = buildContentTypesContainer(acceptHeaderValue, contentTypes); lock(); UtlHashBag* pContent; if (fullState) { // Full content (this is the usual case) pContent = &mContentEntries; } else { // Partial content (used for partial dialog events) pContent = &mPartialContentEntries; } // See if resource-specific content exists container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // There is no resource-specific content. Check if the default // constructor exists. if (container == NULL) { // Construct the key for the default data. UtlString default_key(eventTypeKey); // Look up the constructor. SipPublishContentMgrDefaultConstructor* constructor = dynamic_cast <SipPublishContentMgrDefaultConstructor*> (mDefaultContentConstructors.findValue(&default_key)); // If it exists, call it to publish content for this resource/event. if (constructor) { constructor->generateDefaultContent(this, resourceId, eventTypeKey, eventType); } // See if resource specific content exists now. container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // If content was found, still mark it as default content. if (container) { isDefaultContent = TRUE; } // If still no content was found, check if the default exists. else { container = dynamic_cast <PublishContentContainer*> (mDefaultContentEntries.find(&default_key)); if(container) { isDefaultContent = TRUE; } } } // Within the container, find the content of the right MIME type. if (container) { if (acceptedTypesGiven) { UtlString base_mime_type; // Search for the first content in the container whose // MIME type is in the acceptable list. UtlSListIterator contentIterator(container->mEventContent); HttpBody* bodyPtr; UtlSListIterator versionIterator(container->mEventVersion); UtlInt* versionPtr; while (!foundContent && (bodyPtr = dynamic_cast <HttpBody*> (contentIterator())) && (versionPtr = dynamic_cast <UtlInt*> (versionIterator()))) { // Test if ';' is present in *bodyPtr's MIME type. // (Remember that an HttpBody considered as a UtlString has // the value of its content type.) ssize_t i = bodyPtr->index(';'); // The 'if expression' is TRUE if the MIME type of *bodyPtr // is found in in contentTypes. This is messy, because // *bodyPtr's MIME type may have parameters, which have // to be removed before searching contentTypes. if (contentTypes.find(i == UTL_NOT_FOUND ? bodyPtr : ( base_mime_type.remove(0), base_mime_type.append(*bodyPtr, 0, i), &base_mime_type))) { content = bodyPtr->copy(); version = versionPtr->getValue(); foundContent = TRUE; } } if (!foundContent) { // No content was found that matched the required MIME types. OsSysLog::add(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no content found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s'", key.data(), acceptHeaderValue ? acceptHeaderValue : "[none]", resourceId ? resourceId : "[none]", eventTypeKey, eventType); } } else { // No MIME types were specified, take the first content in the list. HttpBody* bodyPtr = dynamic_cast <HttpBody*> (container->mEventContent.first()); UtlInt* versionPtr = dynamic_cast <UtlInt*> (container->mEventVersion.first()); if (bodyPtr) { content = bodyPtr->copy(); version = versionPtr->getValue(); foundContent = TRUE; } else { // No content was found (at all). OsSysLog::add(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no content found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s'", key.data(), acceptHeaderValue ? acceptHeaderValue : "[none]", resourceId ? resourceId : "[none]", eventTypeKey, eventType); } } } else { // No container found for this resource and event. OsSysLog::add(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no container found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s', fullState = %d", key.data(), acceptHeaderValue ? acceptHeaderValue : "[none]", resourceId ? resourceId : "[none]", eventTypeKey, eventType, fullState); } unlock(); contentTypes.destroyAll(); return (foundContent); }