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;
}
Exemple #2
0
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);
}