// If this is an expires line, then modify it by adding timeNow to the expiration time value.
// Otherwise don't mess with it.
void RegistrationDbTestContext::timeShiftExpiresLine(UtlString& line, long timeNow)
{
   const char* EXPIRES_BEGIN = "<expires>";
   const int EXPIRES_TAG_LENGTH = 9; 
   const char* EXPIRES_END = "</expires>";
   ssize_t pos1, pos2;
   // If the line has an expiration value, then time-shift it
   if (((pos1 = line.index(EXPIRES_BEGIN)) != UTL_NOT_FOUND) &&
       ((pos2 = line.index(EXPIRES_END)) != UTL_NOT_FOUND))
   {
      pos1 += EXPIRES_TAG_LENGTH;    // skip past the tag, to the expires value
      CPPUNIT_ASSERT(pos2 > pos1);   // expires value cannot be empty
      UtlString timeText(line(pos1, pos2 - pos1));
      char* endptr = NULL;
      long timeNumber = strtol(timeText, &endptr, 10);
      CPPUNIT_ASSERT_EQUAL(*endptr, '\0');
      char newTime[20];          // room for up to a 64-bit number, may have minus sign
      int newTimeLen = sprintf(newTime, "%ld", timeNow + timeNumber);
      CPPUNIT_ASSERT(newTimeLen > 0);

      // Replace the old expiration value with the new shifted value
      UtlString lineEnd(line(pos2, line.length() - pos2));
      line.replace(pos1, newTimeLen, newTime);
      line.replace(pos1 + newTimeLen, lineEnd.length(), lineEnd);
   }
}
示例#2
0
// Static callback routine used to find and replace variable string values in
// subscription content.
// For example the NOTIFY message in the SIP stack contains "&version;" rather
// than an actual version number [like "22"].
// The content provided by publish() provides the "context
// independent" part of the content, and the SIP stack keeps knowledge
// of the version number sequence for each subscription.  This
// callback combines these sources of information.
UtlBoolean SipSubscribeServer::standardVersionCallback(SipMessage& notifyRequest,
                                                       int version)
{
   // Search and replace the version number in the Notify.
   UtlBoolean result = FALSE;

   if (notifyRequest.getBody() != NULL)
   {
      UtlString msgBytes;
      ssize_t msgLength;
      // Extract the NOTIFY body as a UtlString.
      notifyRequest.getBody()->getBytes(&msgBytes, &msgLength);
      const char* contentType = notifyRequest.getBody()->getContentType();

      // Look for the placeholder for the version number, "&version;".
      ssize_t msgIndex = msgBytes.index(VERSION_PLACEHOLDER);
      if (msgIndex != UTL_NOT_FOUND)
      {
         char buffer[20];
         sprintf(buffer, "%d", version);
         msgBytes.replace(msgIndex, sizeof (VERSION_PLACEHOLDER) - 1, buffer);

         HttpBody* tempBody =
            new HttpBody(msgBytes.data(), msgBytes.length(), contentType);

         // Write the new message contents (this deletes the old body)
         notifyRequest.setBody(tempBody);
         result = TRUE;
      }
   }

   return result;
}
void CallStateEventBuilder_DB::replaceSingleQuotes(const UtlString& value, UtlString& newValue)
{
    size_t startIndex = 0;
    ssize_t newIndex = 0;

    newValue = value;

    newIndex = newValue.index('\'', startIndex);
    while ((newIndex = newValue.index('\'', startIndex)) != UTL_NOT_FOUND)
    {
        startIndex = newIndex + 2;
        newValue = newValue.replace(newIndex, 1, "\\'");
    }
}
示例#4
0
// Extract the contents of an HttpBody.
UtlString extract_contents(HttpBody* body)
{
   UtlString res;

   res.append("Content-Type: ");
   res.append(body->getContentType());
   res.append("\r\n\r\n");
   res.append(body->getBytes());

   // Replace the boundary string with "[boundary]".
   const char* boundary_string = body->getMultipartBoundary();
   ssize_t location;
   while ((location = res.index(boundary_string)) != UTL_NOT_FOUND)
   {
      res.replace(location, strlen(boundary_string),
                  "[boundary]");
   }

   return res;
}
示例#5
0
文件: CallId.cpp 项目: mranga/sipxecs
// Initialize the chain value.
void CallId::initialize()
{
   // Get the start time.
   OsTime currentTime;
   OsDateTime::getCurTime(currentTime);

   // Get the process ID.
   PID processId;
   processId = OsProcess::getCurrentPID();

   // Get the host identity.
   UtlString thisHost;
   OsSocket::getHostIp(&thisHost);
   // Ensure it does not contain @.
   thisHost.replace('@','*');

   // Force usecs. to be 6 digits with leading zeros so that we do
   // not have to do 64 bit integer math just to build a big unique
   // string.
   char buffer[256];
   sprintf(buffer, "%d/%d.%.6d/%s",
           processId,
           currentTime.seconds(), currentTime.usecs(),
           thisHost.data());
   OsSysLog::add(FAC_SIP, PRI_DEBUG,
                 "CallId::initialize sChainValue generated from '%s'",
                 buffer);
   // Hash them.
   NetMd5Codec encoder;
   encoder.encode(buffer, sChainValue);
   // Truncate the hash to CHAIN_VALUE_LENGTH characters.
   sChainValue.remove(CHAIN_VALUE_LENGTH);

   // Note initialization is done.
   sChainValueInitialized = TRUE;
}
示例#6
0
void Url::gen_value_unescape(UtlString& escapedText)
{
#if 0
   printf("Url::gen_value_unescape before escapedText = '%s'\n",
          escapedText.data());
#endif

    //UtlString unescapedText;
    int numUnescapedChars = 0;
    const char* unescapedTextPtr = escapedText;
    // The number of unescaped characters is always less than
    // or equal to the number of escaped characters.  Therefore
    // we will cheat a little and used the escapedText as
    // the destiniation to directly write characters in place
    // as the append method is very expensive
    char* resultPtr = new char[escapedText.length() + 1];

    // Skip initial whitespace, which may be before the starting double-quote
    // of a quoted string.  Tokens and hosts are not allowed to start with
    // whitespace.
    while (*unescapedTextPtr &&
           (*unescapedTextPtr == ' ' || *unescapedTextPtr == '\t'))
    {
       // Consume the whitespace character.
       unescapedTextPtr++;
       numUnescapedChars++;
    }

    // Examine the first character to see if it is a double-quote.
    if (*unescapedTextPtr == '"')
    {
       // Skip the initial double-quote.
       unescapedTextPtr++;
       while (*unescapedTextPtr)
       {
          // Substitute a (backslash-)quoted-pair.
          if (*unescapedTextPtr == '\\')
          {
             // Get the next char.
             unescapedTextPtr++;
             // Don't get deceived if there is no next character.
             if (*unescapedTextPtr)
             {
                // The next character is copied unchanged.
                resultPtr[numUnescapedChars] = *unescapedTextPtr;
                numUnescapedChars++;
             }
          }
          // A double-quote without backslash ends the string.
          else if (*unescapedTextPtr == '"')
          {
             break;
          }
          // Char is face value.
          else
          {
             resultPtr[numUnescapedChars] = *unescapedTextPtr;
             numUnescapedChars++;
          }
          // Go to the next character
          unescapedTextPtr++;
       }
    }
    else
    {
       // It is a token or host, and can be copied unchanged.
       while (*unescapedTextPtr)
       {
          resultPtr[numUnescapedChars] = *unescapedTextPtr;
          numUnescapedChars++;
          // Go to the next character
          unescapedTextPtr++;
       }
    }
    
    // Copy back into the UtlString.
    resultPtr[numUnescapedChars] = '\0';
    escapedText.replace(0, numUnescapedChars, resultPtr);
    escapedText.remove(numUnescapedChars);
    delete[] resultPtr;

#if 0
   printf("Url::gen_value_unescape after escapedText = '%s'\n",
          escapedText.data());
#endif
}
示例#7
0
AuthPlugin::AuthResult
CallerAlias::authorizeAndModify(const UtlString& id,    /**< The authenticated identity of the
                                                         *   request originator, if any (the null
                                                         *   string if not).
                                                         *   This is in the form of a SIP uri
                                                         *   identity value as used in the
                                                         *   credentials database (user@domain)
                                                         *   without the scheme or any parameters.
                                                         */
                                const Url&  requestUri, ///< parsed target Uri
                                RouteState& routeState, ///< the state for this request.  
                                const UtlString& method,///< the request method
                                AuthResult  priorResult,///< results from earlier plugins.
                                SipMessage& request,    ///< see AuthPlugin regarding modifying
                                bool bSpiralingRequest, ///< spiraling indication 
                                UtlString&  reason      ///< rejection reason
                                )
{
   // get the call-id to use in logging
   UtlString callId;
   request.getCallIdField(&callId);

   if (   (priorResult != DENY) // no point in modifying a request that won't be sent
       )   
   {
      UtlString callerFrom;
      UtlString callerFromTagOffsetStr;
      UtlString aliasFrom;
      UtlString aliasFromTagOffsetStr;
      UtlString originalFromTag;

      if (   !routeState.getParameter(mInstanceName.data(), CALLER_FROM_PARAM, callerFrom)
          || !routeState.getParameter(mInstanceName.data(), CALLER_TAG_OFFSET_PARAM, callerFromTagOffsetStr)
          || !routeState.getParameter(mInstanceName.data(), ALIAS_FROM_PARAM, aliasFrom)
          || !routeState.getParameter(mInstanceName.data(), ALIAS_TAG_OFFSET_PARAM, aliasFromTagOffsetStr)
          || !routeState.originalCallerFromTagValue(mInstanceName.data(), originalFromTag)
          )
      {
         if (   routeState.isMutable()
             && routeState.directionIsCallerToCalled(mInstanceName.data())
             ) // a new dialog?
         {
            /*
             * Get the callers identity by getting the caller URI and:
             *    remove all parameters
             *    remove the scheme name
             */
            UtlString callerIdentity;

            UtlString originalFromField;
            request.getFromField(&originalFromField);
            Url originalFromUrl(originalFromField);
            
            /*
             * Extract the from identity as a key for the caller alias table
             * Start with the From header field (someday we should use the Identity if present)
             */
            Url fromUrl(originalFromUrl);
            fromUrl.removeParameters(); // parameters are not relevant for this 
         
            Url::Scheme fromUrlScheme = fromUrl.getScheme();
            switch (fromUrlScheme)
            {
            case Url::SipsUrlScheme:
               // sips and sip are equivalent for identity purposes,
               //   so just set to sip 
               fromUrl.setScheme(Url::SipUrlScheme);
               //   and fall through to extract the identity...

            case Url::SipUrlScheme:
               // case Url::TelUrlScheme: will go here, since 'tel' and 'sip' are the same length
               fromUrl.getUri(callerIdentity);
               callerIdentity.remove(0,4 /* strlen("sip:") */); // strip off the scheme name
               break;

            default:
               // for all other schemes, treat identity as null
               Os::Logger::instance().log(FAC_SIP, PRI_WARNING,
                             "CallerAlias[%s]::check4andApplyAlias From uses unsupported scheme '%s'"
                             " - using null identity",
                             mInstanceName.data(),
                             Url::schemeName(fromUrlScheme)
                             );
               break;
            }

            /*
             * Determine whether the identity is one for which this proxy
             * is authoritative; if not, we will not use wildcard matches.
             */
            bool identityIsLocal = mpSipRouter->isLocalDomain(fromUrl);
            
            // now we have callerIdentity set; use for looking up each contact.
            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                          "CallerAlias[%s]::check4andApplyAlias "
                          "\n  caller '%s' %s",
                          mInstanceName.data(),
                          callerIdentity.data(),
                          identityIsLocal ? "is local" : "is not local"
                          );

            /*
             * Examine the request URI,
             * checking for a caller alias set for its domain(including asssociated gateway sipxecsLineid)  with callerIdentity
             */

            UtlString sipxecsLineIdField;
            requestUri.getUrlParameter(SIPX_SIPXECS_LINEID_URI_PARAM, sipxecsLineIdField);

            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                             "getUrlParameter: sipxecsLineid[%s]"
                             " in CallerAlias",
                             sipxecsLineIdField.data()
                             );

            UtlString targetDomain;
            requestUri.getHostWithPort(targetDomain);

            if (!(sipxecsLineIdField.isNull()))
            {
                targetDomain.append(";").append(SIPX_SIPXECS_LINEID_URI_PARAM).append("=").append(sipxecsLineIdField.data());
            }

            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                          "CallerAlias::targetDomain [%s]",
                          targetDomain.data()
                          );

            // look up any caller alias for this identity and contact domain
            UtlString callerAlias;
            if (identityIsLocal && getCallerAlias(callerIdentity, targetDomain, callerAlias) )
            {
               // found a caller alias, so rewrite the From information
               /*
                * The From header requires special handling
                * - we need to preserve the tag, if any, from the original header
                */
               originalFromUrl.getFieldParameter("tag", originalFromTag);

               Url newFromUrl(callerAlias.data());
               newFromUrl.removeFieldParameter("tag"); // specifying a tag is a no-no
               if ( !originalFromTag.isNull() )
               {
                  newFromUrl.setFieldParameter("tag", originalFromTag.data());
               }
               UtlString newFromFieldValue;
               newFromUrl.toString(newFromFieldValue);
                   
               // log the change we are making before stripping the tag from the field values
               Os::Logger::instance().log( FAC_SIP, PRI_INFO,
                             "CallerAlias[%s]::check4andApplyAlias call %s set caller alias\n"
                             "  Original-From: %s\n"
                             "  Aliased-From:  %s",
                             mInstanceName.data(), callId.data(),
                             originalFromField.data(),
                             newFromFieldValue.data()
                             );

               // rewrite the caller identity with the aliased value
               request.setRawFromField(newFromFieldValue.data());

               // Factor the tag values out of the field values stored in the RouteState
               //  We do this because otherwise we'll end up encoding and sending two copies
               //  of the tag; since some phones send really long tag values (no one knows why),
               //  this can cause such large Record-Route headers that they cause interop problems.
               if ( ! originalFromTag.isNull() )
               {
                  // find the offset of the tag value in the callers from field
                  ssize_t callerFromTagOffset;
                  callerFromTagOffset = originalFromField.index(originalFromTag);
                  callerFromTagOffsetStr.appendNumber(callerFromTagOffset);
                  // strip the tag value from the original From value to be stored in the RouteState
                  originalFromField.replace(callerFromTagOffset, originalFromTag.length(), "");
                  
                  // find the offset of the tag value in the aliased from field
                  ssize_t aliasFromTagOffset;
                  aliasFromTagOffset = newFromFieldValue.index(originalFromTag);
                  aliasFromTagOffsetStr.appendNumber(aliasFromTagOffset);
                  // strip the tag value from the aliased From value to be stored in the RouteState
                  newFromFieldValue.replace(aliasFromTagOffset, originalFromTag.length(), "");
               }

               // save the original and new values so that we can fix them later
               routeState.setParameter(mInstanceName.data(),
                                       CALLER_FROM_PARAM,originalFromField);
               routeState.setParameter(mInstanceName.data(),
                                       CALLER_TAG_OFFSET_PARAM,callerFromTagOffsetStr);
               routeState.setParameter(mInstanceName.data(),
                                       ALIAS_FROM_PARAM,newFromFieldValue);
               routeState.setParameter(mInstanceName.data(),
                                       ALIAS_TAG_OFFSET_PARAM,aliasFromTagOffsetStr);
            }
            else
            {
               Os::Logger::instance().log( FAC_SIP, PRI_DEBUG,
                             "CallerAlias[%s]::check4andApplyAlias call %s found no alias",
                             mInstanceName.data(), callId.data()
                             );
            }
         }
         else
         {
            Os::Logger::instance().log(FAC_SIP, PRI_DEBUG,
                          "CallerAlias[%s]::authorizeAndModify "
                          "not mutable - no rewrite",
                          mInstanceName.data()                          
                          );
         }
      }
      else // the callerFrom and aliasFrom parameters were found
      {
         /*
          * This request has had its From rewritten, so fix either the From
          * or the To depending on which direction this request is going.
          */
         if (!request.isResponse()) // can't modify responses, so don't bother
         {
            size_t tagOffset;
            
            if (routeState.directionIsCallerToCalled(mInstanceName.data()))
            {
               // replace the from tag value in the stored aliased header
               tagOffset = strtol(aliasFromTagOffsetStr.data(), NULL, 10);
               aliasFrom.insert(tagOffset, originalFromTag);

               // put the aliased header into the message
               request.setRawFromField(aliasFrom);
               Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, "CallerAlias[%s]::authorizeAndModify "
                             "call %s reset From",
                             mInstanceName.data(), callId.data()
                             );
            }
            else // direction is Called to Caller
            {
               // replace the from tag value in the stored original header
               tagOffset = strtol(callerFromTagOffsetStr.data(), NULL, 10);
               callerFrom.insert(tagOffset, originalFromTag);

               request.setRawToField(callerFrom.data());
               Os::Logger::instance().log(FAC_AUTH, PRI_DEBUG, "CallerAlias[%s]::authorizeAndModify "
                             "call %s reset To",
                             mInstanceName.data(), callId.data()
                             );
            }
         }
      }
   }
   return AuthPlugin::CONTINUE;
}