UtlBoolean SipSubscribeServerEventHandler::getNotifyContent(const UtlString& resourceId,
                                                            const UtlString& eventTypeKey,
                                                            const UtlString& eventType,
                                                            SipPublishContentMgr& contentMgr,
                                                            const char* acceptHeaderValue,
                                                            SipMessage& notifyRequest,
                                                            int& version)
{
    UtlBoolean gotBody = FALSE;
    // Default behavior is to just go get the content from
    // the content manager and attach it to the notify
    HttpBody* messageBody = NULL;
    UtlBoolean isDefaultEventContent;
    gotBody = contentMgr.getContent(resourceId,
                                    eventTypeKey,
                                    eventType,
                                    acceptHeaderValue,
                                    messageBody,
                                    version,
                                    isDefaultEventContent);

    // The body will be freed with the NOTIFY message.
    if(messageBody)
    {
        const char* contentTypePtr = messageBody->getContentType();
        UtlString contentType;
        if(contentTypePtr)
        {
            contentType = contentTypePtr;
        }
        else
        {
            OsSysLog::add(FAC_SIP, PRI_ERR,
                "SipSubscribeServerEventHandler::getNotifyContent body published for resourceId: '%s' eventTypeKey: '%s' with no content type",
                resourceId.data() ? resourceId.data() : "<null>", 
                eventTypeKey.data() ? eventTypeKey.data() : "<null>");

            contentType = "text/unknown";
        }
          
        notifyRequest.setContentType(contentType);
        notifyRequest.setBody(messageBody);
        
        UtlString request;
        ssize_t requestLength;
        notifyRequest.getBytes(&request, &requestLength);   
        OsSysLog::add(FAC_SIP, PRI_DEBUG,
                      "SipSubscribeServerEventHandler::getNotifyContent resourceId '%s', eventTypeKey '%s' contentType '%s' NOTIFY message length = %zu, message = '%s'",
                      resourceId.data(), eventTypeKey.data(),
                      contentType.data(), requestLength, request.data());
    }

    return(gotBody);
}
示例#2
0
// Construct a MimeBodyPart from an HttpBody and a list of parameters.
MimeBodyPart::MimeBodyPart(const HttpBody& httpBody,
                           //< Provides the bytes of the body.
                           const UtlDList& parameters
                           //< Provides the parameters.
   ) :
   HttpBody(httpBody),
   mpParentBody(NULL),
   mParentBodyRawStartIndex(-1),
   mRawBodyLength(-1),
   mParentBodyStartIndex(-1),
   mBodyLength(-1)
{
   // Copy the parameters to mNameValues.
   UtlDListIterator iterator(parameters);
   NameValuePair* nvp;
   while((nvp = (NameValuePair*) iterator()))
   {
      mNameValues.append(new NameValuePair(nvp->data(), nvp->getValue()));
   }
   // Add the Content-Type parameter, taken from the HttpBody.
   mNameValues.append(new NameValuePair(HTTP_CONTENT_TYPE_FIELD,
                                        httpBody.getContentType()));
   // Add the Content-Transfer-Encoding parameter.
   mNameValues.append(new NameValuePair(HTTP_CONTENT_TRANSFER_ENCODING_FIELD,
                                        HTTP_CONTENT_TRANSFER_ENCODING_BINARY));

   // Members that reference the parent will be corrected later.
}
示例#3
0
void HttpRequestContext::extractPostCgiVariables(const HttpBody& body)
{
    int length;
    UtlString bodyBytes;

    body.getBytes(&bodyBytes, &length);
    parseCgiVariables(bodyBytes.data());
    bodyBytes.remove(0);
}
// Dump the object's internal state.
void PublishContentContainer::dumpState()
{
   // indented 8 and 10

   UtlString key(*this);
   key.replace(sizeof (CONTENT_KEY_SEPARATOR) - 1,
               key.index(CONTENT_KEY_SEPARATOR),
               " ");
   Os::Logger::instance().log(FAC_RLS, PRI_INFO,
                 "\t        PublishContentContainer %p UtlString = '%s'",
                 this, data());

   int index = 0;
   UtlSListIterator content_itor(mEventContent);
   HttpBody* body;
   while ((body = dynamic_cast <HttpBody*> (content_itor())))
   {
      Os::Logger::instance().log(FAC_RLS, PRI_INFO,
                    "\t          mEventContent[%d] = '%s':'%s'",
                    index, body->data(), body->getBytes());
      index++;
   }
}
示例#5
0
// Dump the object's internal state.
void PublishContentContainer::dumpState()
{
    // indented 8 and 10

    OsSysLog::add(FAC_RLS, PRI_INFO,
                  "\t        PublishContentContainer %p UtlString = '%s'",
                  this, data());

    int index = 0;
    UtlSListIterator content_itor(mEventContent);
    UtlSListIterator version_itor(mEventVersion);
    HttpBody* body;
    while ((body = dynamic_cast <HttpBody*> (content_itor())))
    {
        UtlInt* version = dynamic_cast <UtlInt*> (version_itor());
        OsSysLog::add(FAC_RLS, PRI_INFO,
                      "\t          mEventVersion[%d] = %" PRIdPTR ", "
                      "mEventContent[%d] = '%s':'%s'",
                      index, version->getValue(),
                      index, body->data(), body->getBytes());
        index++;
    }
}
示例#6
0
//! Generate the HttpBody for the current state of the resource list.
HttpBody* ResourceList::generateRlmiBody(UtlBoolean consolidated,
                                         UtlBoolean fullRlmi,
                                         UtlSList& listToSend)
{
   if (Os::Logger::instance().willLog(FAC_RLS, PRI_DEBUG))
   {
      UtlString l;

      UtlSListIterator resourcesItor(listToSend);
      ResourceReference* resource;
      while ((resource = dynamic_cast <ResourceReference*> (resourcesItor())))
      {
         l.append(*resource->getUri());
         l.append(",");
      }
      if (!l.isNull())
      {
         l.remove(l.length() - 1);
      }

      Os::Logger::instance().log(FAC_RLS, PRI_DEBUG,
                    "ResourceList::generateRlmiBody cons=%d URI='%s' full=%d listToSend='%s'",
                    consolidated,
                    (consolidated ? mResourceListNameCons.data() : mResourceListName.data()),
                    fullRlmi,
                    l.data());
   }

   // Construct the multipart body.
   // We add the <...> here, as they are used in all the contexts where
   // rlmiBodyPartCid appears.
   UtlString rlmiBodyPartCid;
   rlmiBodyPartCid += "<rlmi@";
   rlmiBodyPartCid += getResourceListServer()->getDomainName();
   rlmiBodyPartCid += ">";

   UtlString content_type(CONTENT_TYPE_MULTIPART_RELATED
                          ";type=\"" RLMI_CONTENT_TYPE "\""
                          ";start=\"");
   content_type += rlmiBodyPartCid;
   content_type += "\"";
   HttpBody* body = new HttpBodyMultipart(content_type);

   // This is the Resource List Meta-Information, XML describing the resources
   // and their instances.  It is the main part of the NOTIFY body.
   UtlString rlmi;

   // Generate the initial part of the RLMI.
   rlmi += "<?xml version=\"1.0\"?>\r\n";
   rlmi += "<list xmlns=\"" RLMI_XMLNS "\" uri=\"";
   XmlEscape(rlmi,
             consolidated ? mResourceListNameCons : mResourceListName);
   // Placeholder for version from SIP stack.
   rlmi += "\" version=\"" VERSION_PLACEHOLDER "\" ";

   // Generate either the full or the partial RLMI.
   if (fullRlmi)
   {
      rlmi += "fullState=\"true\">\r\n";
   }
   else
   {
      rlmi += "fullState=\"false\">\r\n";
   }

   // If we implemented names for resource lists, <name> elements would be added here.

   // Iterate through the resources.
   UtlSListIterator resourcesItor(listToSend);
   ResourceReference* resource;
   while ((resource = dynamic_cast <ResourceReference*> (resourcesItor())))
   {
      // Add the content for the resource.
      resource->generateBody(rlmi, *body, consolidated);
   }

   // Generate the postamble for the resource list.
   rlmi += "</list>\r\n";

   // Construct the RLMI body part.
   HttpBody rlmi_body(rlmi.data(), rlmi.length(), RLMI_CONTENT_TYPE);
   UtlDList rlmi_body_parameters;
   rlmi_body_parameters.append(new NameValuePair(HTTP_CONTENT_ID_FIELD,
                                                 rlmiBodyPartCid));

   // Attach the RLMI.
   body->appendBodyPart(rlmi_body, rlmi_body_parameters);

   // Clean up the parameter list.
   rlmi_body_parameters.destroyAll();

   return body;
}
示例#7
0
// Add to the HttpBody the current state of the resource.
void ResourceCached::generateBody(UtlString& rlmi,
                                  HttpBody& body,
                                  UtlBoolean consolidated,
                                  const UtlString& nameXml,
                                  const UtlString& displayName) const
{
   // Generate the preamble for the resource.
   rlmi += "  <resource uri=\"";
   XmlEscape(rlmi, *(static_cast <const UtlString*> (this)));
   rlmi += "\">\r\n";
   if (!nameXml.isNull())
   {
      rlmi += "    ";
      rlmi += nameXml;
   }

   if (consolidated)
   {
      // If consolidating resource instances, generate the XML for the
      // unified resource instance.
      rlmi += "    <instance id=\"consolidated\" state=\"active\"";

      UtlString contentBodyPartCid;
      // Use the count of parts in 'body' to generate a unique identifier for
      // each part.
      contentBodyPartCid.appendNumber(body.getMultipartCount());
      contentBodyPartCid += "@";
      contentBodyPartCid += getResourceListServer()->getDomainName();

      rlmi += " cid=\"";
      rlmi += contentBodyPartCid;
      rlmi += "\"";

      // Now add the <...> and use it in the header.
      contentBodyPartCid.prepend("<");
      contentBodyPartCid.append(">");

      // Create a single HttpBody to contain the unified dialog event.
      UtlString dialog_event;

      // XML declaration is optional, but Broadworks uses it.
      dialog_event += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
      dialog_event += BEGIN_DIALOG_INFO;
      dialog_event += VERSION_EQUAL;
      dialog_event += "\"";
      // The consolidated dialog events need to have persistent
      // version numbers, as they all have the same instance id.
      // So we use a global version number in the ResourceListSet.
      dialog_event.appendNumber(getResourceListSet()->getVersion());
      dialog_event += "\"";
      dialog_event += STATE_EQUAL;
      dialog_event += "\"full\"";
      dialog_event += ENTITY_EQUAL;
      dialog_event += "\"";
      dialog_event += *(static_cast <const UtlString*> (this));
      dialog_event += "\">\r\n";
      // Save the length of dialog_event, so we can tell later if
      // any <dialog>s have been added to it.
      unsigned int preamble_length = dialog_event.length();

      // Call the ContactSet to generate the consolidated dialog event body.
      if (mContactSetP)
      {
         mContactSetP->generateBody(dialog_event, body, consolidated,
                                    displayName);
      }

      // If no <dialog>s have been added, we have to add a dummy
      // <dialog> to carry the display name.
      if (dialog_event.length() == preamble_length)
      {
         dialog_event +=
            "<dialog id=\";\"><state>terminated</state><local><identity display=\"";
         XmlEscape(dialog_event, displayName);
         dialog_event += "\">";
         XmlEscape(dialog_event, *(static_cast <const UtlString*> (this)));
         dialog_event += "</identity></local></dialog>\r\n";
      }

      dialog_event += END_DIALOG_INFO;

      // Insert the consolidated dialog event body into the multiplart body.
      HttpBody content_body(dialog_event.data(),
                            dialog_event.length(),
                            DIALOG_EVENT_CONTENT_TYPE);
      UtlDList content_body_parameters;
      content_body_parameters.append(
         new NameValuePair(HTTP_CONTENT_ID_FIELD,
                           contentBodyPartCid));
      body.appendBodyPart(content_body, content_body_parameters);
      content_body_parameters.destroyAll();

      // Finish the <instance> element.
      rlmi += "/>\r\n";
   }
   else
   {
      // Call the ContactSet to do the work.
      if (mContactSetP)
      {
         mContactSetP->generateBody(rlmi, body, consolidated, displayName);
      }
   }   
   
// Generate the postamble for the resource.
   rlmi += "  </resource>\r\n";
}
示例#8
0
// Add to the HttpBody the current state of the resource.
void ResourceInstance::generateBody(UtlString& rlmi,
                                    HttpBody& body,
                                    UtlBoolean consolidated,
                                    const UtlString& displayName) const
{
   OsSysLog::add(FAC_RLS, PRI_DEBUG,
                 "ResourceInstance::generateBody mInstanceName = '%s', consolidated = %d, displayName = '%s', mContentPresent = %d",
                 mInstanceName.data(), consolidated, displayName.data(),
                 mContentPresent);

   if (consolidated)
   {
      if (mContentPresent)
      {
         // If this is a consolidated dialog event list, edit the
         // stored XML into the right form and append each dialog
         // to the resource list event notice.

         TiXmlUtlStringWriter writer(&rlmi);

         // Iterate through all the <dialog> elements.
         UtlHashMapIterator itor(mXmlDialogs);
         UtlContainable* id;
         while ((id = itor()))
         {
            UtlVoidPtr* p = dynamic_cast <UtlVoidPtr*> (itor.value());
            TiXmlElement* dialog_element =
               static_cast <TiXmlElement*> (p->getValue());

            // Now that we've got a <dialog> element, edit it to fit
            // into a consolidated event notice.

            // Get the display name right.
            // Find the <local> element, which we know exists due to
            // earlier processing.
            TiXmlNode* local = dialog_element->FirstChild("local");
            // Find the <local><identity> element, which we know
            // exists due to earlier processing.
            TiXmlNode* identity = local->FirstChild("identity");
            // Update the display attribute, as that is what will show
            // on the phone.
            identity->ToElement()->
               SetAttribute("display", displayName);

            // Un-parse the dialog into the string for storage.
            writer << *dialog_element;
            writer << "\r\n";
         }
      }
   }
   else
   {
      // Generate the XML for the instance.
      rlmi += "    <instance id=\"";
      XmlEscape(rlmi, mInstanceName);
      rlmi += "\" state=\"";
      // Subscription states don't require escaping.
      rlmi += mSubscriptionState;
      rlmi += "\"";

      // Generate the body part for the instance, if necessary.
      if (mContentPresent)
      {
         UtlString contentBodyPartCid;
         // Use the count of parts in 'body' to generate a unique identifier for
         // each part.
         contentBodyPartCid.appendNumber(body.getMultipartCount());
         contentBodyPartCid += "@";
         contentBodyPartCid += getResourceListServer()->getDomainName();

         rlmi += " cid=\"";
         rlmi += contentBodyPartCid;
         rlmi += "\"";

         // Now add the <...> and use it in the header.
         contentBodyPartCid.prepend("<");
         contentBodyPartCid.append(">");

         HttpBody content_body(mContent.data(),
                               mContent.length(),
                               getResourceListServer()->getContentType());
         UtlDList content_body_parameters;
         content_body_parameters.append(
            new NameValuePair(HTTP_CONTENT_ID_FIELD,
                              contentBodyPartCid));
         body.appendBodyPart(content_body, content_body_parameters);
         content_body_parameters.destroyAll();
      }

      rlmi += "/>\r\n";
   }
}
示例#9
0
// Append a multipart body part to an existing multiparty body.
void HttpBody::appendBodyPart(const HttpBody& body,
                              const UtlDList& parameters)
{
   assert(isMultipart());

   // Construct a new MimeBodyPart for the new body part.
   MimeBodyPart* part = new MimeBodyPart(body, parameters);

   // Insert it as the last body part.
   mBodyParts.append(part);
   mBodyPartCount++;

   // Turn the final boundary into an intermediate boundary.
   mBody.remove(mBody.length() - 4);
   mBody.append("\r\n");

   // Insert the headers.
   ssize_t rawPartStart = mBody.length();
   UtlDListIterator iterator(*part->getParameters());
   NameValuePair* nvp;
   while ((nvp = (NameValuePair*) iterator()))
   {
      mBody.append(nvp->data());
      mBody.append(": ");
      mBody.append(nvp->getValue());
      mBody.append("\r\n");
   }
   mBody.append("\r\n");

   // Insert the body.
   ssize_t partStart = mBody.length();
   const char* bytes;
   ssize_t length;
   body.getBytes(&bytes, &length);
   mBody.append(bytes, length);
   ssize_t partEnd = mBody.length();

   // Update bodyLength.
   bodyLength = mBody.length();

   // Determine if we have to change the boundary string.
   bool change_boundary_string =
      mBody.index(mMultipartBoundary, partStart) != UTL_NOT_FOUND;

   // Add the final boundary.
   mBody.append("\r\n--");
   mBody.append(mMultipartBoundary);
   mBody.append("--\r\n");

   // Update the MimeBodyPart to know where it is contained in the HttpBody.
   part->attach(this,
                rawPartStart, partEnd - rawPartStart,
                partStart, partEnd - partStart);

   // If we have to change the boundary string.
   if (change_boundary_string)
   {
      // Find a new boundary string that isn't in the body.
      do {
         nextBoundary(mMultipartBoundary);
      } while (mBody.index(mMultipartBoundary) != UTL_NOT_FOUND);

      // Replace the old boundary string.
      UtlSListIterator iterator(mBodyParts);
      MimeBodyPart* part;
      while ((part = dynamic_cast<MimeBodyPart*>(iterator())))
      {
            // Replace the boundary string just before this part.
            mBody.replace(part->getRawStart() - (2 + BOUNDARY_STRING_LENGTH),
                          BOUNDARY_STRING_LENGTH,
                          mMultipartBoundary.data(),
                          BOUNDARY_STRING_LENGTH);
      }

      // Replace the boundary string in the final boundary.
      mBody.replace(mBody.length() - (4 + BOUNDARY_STRING_LENGTH),
                    BOUNDARY_STRING_LENGTH,
                    mMultipartBoundary.data(),
                    BOUNDARY_STRING_LENGTH);

      // Replace the boundary string in the Content-Type.
      ssize_t loc = this->index(";" MULTIPART_BOUNDARY_PARAMETER "=\"");
      this->replace(loc + sizeof (";" MULTIPART_BOUNDARY_PARAMETER "=\"") - 1,
                    BOUNDARY_STRING_LENGTH,
                    mMultipartBoundary.data(),
                    BOUNDARY_STRING_LENGTH);
   }
}
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;
}
int
ParserCWHandler::getURL( const MC2String& urlStr, 
                         const MC2String& postData,
                         uint32 peerIP, uint32 fromByte, uint32 toByte,
                         LangTypes::language_t clientLang,
                         const HttpHeader* inHeaders,
                         HttpHeader& outHeaders, MC2String& reply,
                         uint32& startByte, uint32& endByte )
{
   uint32 startTime = TimeUtility::getCurrentTime();

   // Work with url
   MC2String serverURLStr( urlStr );
   mc2dbg2 << "serverURLStr " << serverURLStr << endl;
   updateRequest( serverURLStr, clientLang );

   bool fetchedThruProxy = false;
   if ( serverURLStr.find( "://sendThruProxyServer" ) != MC2String::npos ) {
      // This url should be fetched thru the proxy server
      
      // Remove 'sendThruProxyServer' from URL
      STLStringUtility::replaceString( serverURLStr, 
                                       "://sendThruProxyServer/",
                                       "://" );

      URL url(serverURLStr);
      HttpBody outBody;
      HttpVariableContainer myVar;
      myVar.https = ( serverURLStr.find( "https://" ) != MC2String::npos );
      
      // Fetch the url thru proxy server. If proxy fails it will be fetched without
      // proxy below.
      fetchedThruProxy =
         HttpProxyFunctions::fetchThruProxy( url, &outHeaders, &outBody, m_thread, &myVar );
      if ( fetchedThruProxy ) {
         // Successfully fetched thru proxy
         reply.append( outBody.getBody(), outBody.getBodyLength() );      
      } 
   }
   
   // Work with url
   mc2dbg2 << "serverURLStr " << serverURLStr << endl;
   updateRequest( serverURLStr, clientLang );
   URL url2( serverURLStr );
   int ures = 0;
   uint32 timeout = Properties::getUint32Property( "CW_TIMEOUT", 
                                                   5000 );
   
   if ( ! fetchedThruProxy ) {
      if ( serverURLStr.find( "internalInThisProcess" ) != MC2String::npos ) {
         // Handle internally
         reply.clear();
         if ( serverURLStr.find("/TMap/") != MC2String::npos ) {
            MC2String urlParam = STLStringUtility::basename( url2.getFile() );
            if ( !urlParam.empty() ) {
               DataBuffer* d = m_thread->getTileMap( urlParam.c_str() );
               if ( d != NULL ) {
                  ures = 200;
                  reply.append( reinterpret_cast<char*>( d->getBufferAddress() ),
                                d->getCurrentOffset() );
                  outHeaders.setStartLine( 200 );
               } else {
                  outHeaders.setStartLine( 503 );
               }
               delete d;
            }
         }
      }  else {
         // Send request using the parserthreads urlfetcher
         URLFetcher* f = m_thread->getURLFetcher();
         HttpHeader sendHeaders; // Extra headers to send
         // TODO: Add byterange using fromByte and toByte if not 0,MAX_UINT32
         //       so we don't download whole file all the time.
         MC2String peerIPstr = NetUtility::ip2str( peerIP );
         sendHeaders.addHeaderLine( "X-Forwarded-For", peerIPstr );
         
         static const MC2String notForwardHeadersStr[] = {
            "X-WAYF-CT",
            HttpHeaderLines::CONTENT_TYPE,
            HttpHeaderLines::CONTENT_LENGTH,
            HttpHeaderLines::CONNECTION,
            HttpHeaderLines::TRANSFER_ENCODING,
            HttpHeaderLines::X_FORWARDED_FOR,
            HttpHeaderLines::PROXY_CONNECTION,
            HttpHeaderLines::HOST,
            HttpHeaderLines::TE,
            HttpHeaderLines::TRAILER,
            HttpHeaderLines::KEEP_ALIVE,
            HttpHeaderLines::PROXY_AUTHENTICATE,
            HttpHeaderLines::PROXY_AUTHORIZATION,
            HttpHeaderLines::UPGRADE,
         };
         // TODO: Also remove all headers in Connection: header. Like
         //       "Connection: Keep-Alive, Trailer" should delete those two.
         static const set< MC2String, strNoCaseCompareLess > notForwardHeaders( 
            BEGIN_ARRAY( notForwardHeadersStr ), 
            END_ARRAY( notForwardHeadersStr ) );
         
         if ( inHeaders != NULL ) {
            const HttpHeader::HeaderMap& headers = inHeaders->getHeaderMap();
            for ( HttpHeader::HeaderMap::const_iterator it = headers.begin() ;
                  it != headers.end() ; ++it ) {
               if ( notForwardHeaders.find( it->first ) == 
                    notForwardHeaders.end() ) {
                  sendHeaders.addHeaderLine( it->first, *it->second );
               }
            }
         }
         
         if ( postData.empty() ) {
            ures = f->get(  reply, outHeaders, url2, 
                            timeout, &sendHeaders );
         } else {
            if ( inHeaders->getHeaderValue( "X-WAYF-CT" ) != NULL ) {
               sendHeaders.addHeaderLine( 
                  HttpHeaderLines::CONTENT_TYPE,
                  *inHeaders->getHeaderValue( "X-WAYF-CT" ) );
            } else {
               sendHeaders.addHeaderLine( 
                  HttpHeaderLines::CONTENT_TYPE, 
                  "application/x-www-form-urlencoded" );
            }
            ures = f->post( reply, outHeaders, url2, postData, 
                            timeout, &sendHeaders );
         }
         // Reset user agent
         //f->setDefaultUserAgent();
      }
   } // if (! fetchedThruProxy )
   
   // Remove chunked-encoding from reply (if present)
   const MC2String teh( "Transfer-Encoding" );
   const MC2String* te = outHeaders.getHeaderValue( &teh );
   if ( te != NULL && ( te->find( "chunked") != MC2String::npos ) ) {
      outHeaders.deleteHeaderLine( &teh );
   }
      
   // Check if web updated user
   const MC2String wfidh( "X-WFID-UPDATE" );
   const MC2String* wfid = outHeaders.getHeaderValue( &wfidh );
   if ( wfid != NULL ) {
      // Remove the uin from user cache
      uint32 uin = STLStringUtility::strtoul( *wfid );
      m_group->removeUserFromCache( uin );

      // And remove the header
      outHeaders.deleteHeaderLine( &wfidh );
   }

   // Make reply
   const MC2String eol( "\r\n" );
   if ( fromByte > toByte ) {
      toByte = fromByte;
   }
   const uint32 maxBytes = toByte - fromByte;
   uint32 lastByte = uint32( MAX( int32(reply.size()) - 1, 0 ) );
   startByte = MIN( fromByte, lastByte );
   endByte = startByte + MIN( lastByte - startByte, maxBytes );

   if ( ures > 0 && reply.size() > 0 && 
        (endByte != lastByte || startByte != 0) ) 
   {
      // Set byte range in reply
      MC2String rangeStr( "bytes " );
      STLStringUtility::uint2str( startByte, rangeStr );
      rangeStr.append( "-" );
      STLStringUtility::uint2str( endByte, rangeStr );
      rangeStr.append( "/" );
      STLStringUtility::uint2str( reply.size(), rangeStr ); // Real size
      outHeaders.addHeaderLine( "Content-Range", rangeStr );
      rangeStr = "";
      STLStringUtility::uint2str( endByte - startByte + 1, rangeStr );
      // Set right content length
      outHeaders.addHeaderLine( "Content-Length", rangeStr );
      // Set startline with 206 Partial Content
      MC2String responce( outHeaders.getStartLine()->substr( 0, 9 ) );
      responce.append( "206 Partial Content" );
      responce.append( eol );
      outHeaders.setStartLine( new MC2String( responce ) );
   } else if ( ures < 0 || outHeaders.getStartLine() == NULL ) {
      if ( TimeUtility::getCurrentTime() - startTime >= timeout ) {
         outHeaders.setStartLine( 503 );
      } else {
         outHeaders.setStartLine( 500 );
      }
   } else {
      // Set startline with eol
      outHeaders.setStartLine( 
         new MC2String( StringUtility::trimStartEnd( 
                           *outHeaders.getStartLine() ) + eol ) );
   }

   return ures;
}
示例#12
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);
}