예제 #1
0
void SipDialog::reverseTags(const char* dialogHandle,
                            UtlString& reversedHandle)
{
    UtlString tag1;
    UtlString tag2;
    parseHandle(dialogHandle, reversedHandle, tag1, tag2);
    reversedHandle.capacity(strlen(dialogHandle) + 2);
    reversedHandle.append(DIALOG_HANDLE_SEPARATOR);
    reversedHandle.append(tag2);
    reversedHandle.append(DIALOG_HANDLE_SEPARATOR);
    reversedHandle.append(tag1);
}
예제 #2
0
파일: Url.cpp 프로젝트: John-Chan/sipXtapi
void Url::gen_value_escape(UtlString& unEscapedText)
{
   // Check if there are any characters in unEscapedText that need to be
   // escaped in a field parameter value.
   if (strspn(unEscapedText.data(),
              // Alphanumerics
              "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
              "abcdefghijklmnopqrstuvwxyz"
              "0123456789"
              // Characters allowed in tokens
              "-.!%*_+`'~"
              // Additional characters allowed by the syntax of "host"
              "[]:") != unEscapedText.length())
   {
      // Temporary string to construct the escaped value in.
      UtlString escapedText;
      // Pre-size it to the size of the un-escaped test, plus 2 for
      // the starting and ending double-quotes.
      escapedText.capacity((size_t) unEscapedText.length() + 2);
      const char* unescapedTextPtr = unEscapedText.data();

      // Start with double-quote.
      escapedText.append("\"");

      // Process each character of the un-escaped value.
      while(*unescapedTextPtr)
      {
         char unEscapedChar = *unescapedTextPtr;
         if (unEscapedChar == '"' || unEscapedChar == '\\')
         {
            // Construct a little 2-character string and append it.
            char escapedChar[2];
            escapedChar[0] = '\\';
            escapedChar[1] = *unescapedTextPtr;
            escapedText.append(&unEscapedChar, 2);
        }
        else
        {
           // Append the character directly.
           escapedText.append(&unEscapedChar, 1);
        }
         // Consider the next character.
         unescapedTextPtr++;
      }

      // End with double-quote.
      escapedText.append("\"");

      // Write the escaped string into the argumemt.
      unEscapedText = escapedText;
   }
}
예제 #3
0
/* //////////////////////////// PRIVATE /////////////////////////////////// */
UtlString LogNotifier::escape(const UtlString& source)
{
   UtlString    results;
   const char* pStart = source.data() ;
   const char* pTraverse = pStart ;
   const char* pLast = pStart ;

   results.capacity(source.length() + 100);
   while (*pTraverse)
   {
      switch (*pTraverse)
      {
         case '\\':
            // Copy old data
            if (pLast < pTraverse)
            {
               results.append(pLast, pTraverse-pLast);
            }
            pLast = pTraverse + 1 ;

            // Add escaped Text
            results.append("\\\\") ;
            break ;
         case '\r':
            // Copy old data
            if (pLast < pTraverse)
            {
               results.append(pLast, pTraverse-pLast);
            }
            pLast = pTraverse + 1 ;

            // Add escaped Text
            results.append("\\r") ;
            break ;
         case '\n':
            // Copy old data
            if (pLast < pTraverse)
            {
               results.append(pLast, pTraverse-pLast);
            }
            pLast = pTraverse + 1 ;

            // Add escaped Text
            results.append("\\n") ;
            break ;
         case '\"':
            // Copy old data
            if (pLast < pTraverse)
            {
               results.append(pLast, pTraverse-pLast);
            }
            pLast = pTraverse + 1 ;

            // Add escaped Text
            results.append("\\\"") ;
            break ;
         default:
            break ;
      }
      pTraverse++ ;
   }

   // if nothing to escape, short-circuit
   if (pLast == pStart)
   {
      return source ;
   }
   else if (pLast < pTraverse)
   {
      results.append(pLast, pTraverse-pLast);
   }

   return results ;
}
예제 #4
0
void HttpFileAccess::sendFile(const UtlString& path,
                              const UtlString& peerName,
                              const HttpRequestContext& requestContext,
                              const HttpMessage& request,
                              HttpMessage*& response
                              )
{
   UtlString message;
   
   int file = open(path.data(), O_RDONLY);
   if (0 <= file)
   {
      UtlString fileBuffer;
      if (fileBuffer.capacity(MAX_FILE_CHUNK_SIZE + 1) >= MAX_FILE_CHUNK_SIZE + 1)
      {
         response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION_1_1,
                                              HTTP_OK_CODE, HTTP_OK_TEXT);
         response->useChunkedBody(true);

         // @TODO Annotate file resources with a mime type?

         // add a Content-Disposition header to suggest saving as the basename of the file
         response->setContentType("application/octet-stream");
         UtlString dispositionValue;
         UtlString basename;
         ssize_t finalSlash = path.last('/');
         if (UTL_NOT_FOUND != finalSlash)
         {
            basename.append(path, finalSlash+1, path.length()-finalSlash);
         }
         else
         {
            basename.append(path); // don't think this should ever be true....
         }
         dispositionValue.append("attachment; filename=\"");
         dispositionValue.append(basename);
         dispositionValue.append("\"");
         response->setHeaderValue(HTTP_CONTENT_DISPOSITION_FIELD,dispositionValue.data());

         bool    writtenOk = response->writeHeaders(requestContext.socket());
         ssize_t bytes;
         Int64   totalBytes = 0;
         Int64   chunks = 0;
         while (   writtenOk
                && (bytes = read(file, (void*)fileBuffer.data(),
                                 MAX_FILE_CHUNK_SIZE)))
         {
            fileBuffer.setLength(bytes);
            writtenOk = response->writeChunk(requestContext.socket(), fileBuffer);
            if (writtenOk)
            {
               totalBytes += bytes;
               chunks++;
            }
            OsSysLog::add(FAC_SUPERVISOR, PRI_DEBUG,
                          "file block %"FORMAT_INTLL"d %zd %s", chunks, bytes,
                          writtenOk ? "ok" : "failed");
         }
         if (writtenOk)
         {
            response->writeEndOfChunks(requestContext.socket());

            message.append(" sent file '");
            message.append(path);
            message.append("' (");
            message.appendNumber(totalBytes,"%"FORMAT_INTLL"d");
            message.append(" bytes in ");
            message.appendNumber(chunks,"%"FORMAT_INTLL"d");
            message.append(" chunks) to peer ");
            message.append(peerName);
            OsSysLog::add(FAC_SUPERVISOR, PRI_INFO, "HttpFileAccess::processRequest %s",
                          message.data());
         }
         else
         {
            message.append("error writing response after ");
            message.appendNumber(totalBytes,"%"FORMAT_INTLL"d");
            message.append(" body bytes in ");
            message.appendNumber(chunks,"%"FORMAT_INTLL"d");
            message.append(" chunks) to peer ");
            message.append(peerName);
            OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest %s",
                          message.data());
         }

         /*
          * We've already written the response, so prevent HttpServer from sending it by
          * not passing it back.
          */
         delete response;
         response = NULL;
      }
      else
      {
         // Send out-of-resources message
         message.append("Supervisor Buffer Exhausted");
         response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                              HTTP_OUT_OF_RESOURCES_CODE,
                                              message.data());
         response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
         response->setBody(new HttpBody(message.data(),message.length()));
         response->setContentLength(message.length());

         OsSysLog::add(FAC_SUPERVISOR, PRI_ERR,
                       "HttpFileAccess::processRequest from %s %s",
                       peerName.data(), message.data());
      }
   }
   else
   {
      int       httpStatusCode;
      UtlString httpStatusText;

      switch (errno)
      {
      case EACCES:
         httpStatusCode = HTTP_FORBIDDEN_CODE;
         httpStatusText = "File Access Denied";
         break;

      case ENOENT:
         httpStatusCode = HTTP_FILE_NOT_FOUND_CODE;
         httpStatusText = HTTP_FILE_NOT_FOUND_TEXT;
         break;

      default:
         httpStatusCode = HTTP_SERVER_ERROR_CODE;
         httpStatusText = HTTP_SERVER_ERROR_TEXT;
         break;
      }

      message.append("File '");
      message.append(path);
      message.append("' errno ");
      message.appendNumber(errno);
      message.append(" ");

      char errnoMsg[1024];
      strerror_r(errno, errnoMsg, sizeof(errnoMsg));
      message.append(errnoMsg);

      OsSysLog::add(FAC_SUPERVISOR, PRI_ERR, "HttpFileAccess::processRequest from %s %s",
                    peerName.data(), message.data());

      response->setResponseFirstHeaderLine(HTTP_PROTOCOL_VERSION,
                                           httpStatusCode,
                                           httpStatusText);
      response->setBody(new HttpBody(message.data(),message.length()));
      response->setContentType(CONTENT_TYPE_TEXT_PLAIN);
      response->setContentLength(message.length());
   }
}
예제 #5
0
/**
 * The contents of the source string are appended to the destination string, with all
 * characters escaped as described above.
 * @returns true for success, false if an error was returned from any UtlString operation.
 */
bool XmlEscape(UtlString& destination, const UtlString& source)
{
   bool resultOk = false;
   size_t srcLen = source.length();

   if (srcLen > 0)
   {
      // make sure that the destination is at least large enough to add the source
      size_t minDstLen = destination.length() + srcLen;
      if (destination.capacity(minDstLen) >= minDstLen)
      {
         RegEx copyChars(CopyChars);
      
         UtlString escapeChar;
         bool matched;
         // each iteration picks up leading n valid chars (n may be zero) and one that needs to be escaped.
         for (matched = copyChars.Search(source.data(), srcLen);
              matched;
              matched = copyChars.SearchAgain()
              )
         {
            // copy any leading characters that don't need to be escaped
            copyChars.MatchString(&destination,1);

            if (copyChars.MatchString(&escapeChar,2)) // was there an escaped character?
            {
               switch(*escapeChar.data())
               {
               case '\x22' /* " */:
                  destination.append(QUOTE);
                  break;
               case '\x26' /* & */:
                  destination.append(AMPERSAND);
                  break;
               case '\x27' /* ' */:
                  destination.append(APOSTROPHE);
                  break;
               case '\x3c' /* < */:
                  destination.append(LESS_THAN);
                  break;
               case '\x3e' /* > */:
                  destination.append(GREATER_THAN);
                  break;
               default:
               {
                  // outside the valid range; escape as numeric entity
                  char hexval[7];
                  sprintf(hexval, "&#x%02x;", *escapeChar.data());
                  destination.append(hexval);
               }
               break;
               }
               escapeChar.remove(0); // clear for next iteration
            }
         }
         resultOk = true;
      }
      else
      {
         // UtlString capacity failed
         assert(false);
      }
   }
   else
   {
      resultOk = true; // empty source - easy
   }
   return resultOk;
}
예제 #6
0
/**
 * The contents of the source string are appended to the destination string, with all
 * characters unescaped as described above.
 * @returns true for success, false if an error was returned from any UtlString operation.
 */
bool XmlUnEscape(UtlString& destination, const UtlString& source)
{
   bool resultOk = false;
   size_t srcLen = source.length();

   if (srcLen > 0)
   {
      // make sure that the destination is large enough to add the source (which cannot grow)
      size_t minDstLen = destination.length() + srcLen;
      if (destination.capacity(minDstLen) >= minDstLen)
      {
         RegEx entity(Entity);
      
         UtlString number;
         bool matched;
         bool matchedOnce;
         bool firstMatch = true;
         // each iteration picks up leading n valid chars (n may be zero) and one that needs to be escaped.
         for (matchedOnce = matched = entity.Search(source.data(), srcLen);
              matched;
              matched = entity.SearchAgain()
              )
         {
            if (firstMatch)
            {
               // copy any leading characters that don't need to be escaped
               entity.BeforeMatchString(&destination);
               firstMatch = false;
            }

            if      (entity.MatchString(NULL,1)) 
            {
               destination.append('"');
            }
            else if (entity.MatchString(NULL,2)) 
            {
               destination.append('&');
            }
            else if (entity.MatchString(NULL,3)) 
            {
               destination.append("'");
            }
            else if (entity.MatchString(NULL,4)) 
            {
               destination.append('<');
            }
            else if (entity.MatchString(NULL,5)) 
            {
               destination.append('>');
            }
            else if (entity.MatchString(&number,6)) 
            {
               char* unconverted;
               int decimalNum = strtol(number.data(), &unconverted, /* base */ 10);
               
               if ('\000'==*unconverted && decimalNum >= 0 && decimalNum < 256)
               {
                  destination.append(decimalNum);
               }
               else
               {
                  // invalid decimal numeric entity - transcribe it untranslated
                  destination.append(number);
               }
               number.remove(0); // clear for next iteration
            }
            else if (entity.MatchString(&number,7)) 
            {
               char* unconverted;
               int decimalNum = strtol(number.data(), &unconverted, /* base */ 16);
               
               if ('\000'==*unconverted && decimalNum >= 0 && decimalNum < 256)
               {
                  destination.append(decimalNum);
               }
               else
               {
                  // invalid decimal numeric entity - transcribe it untranslated
                  destination.append(number);
               }
               number.remove(0); // clear for next iteration
            }
            else
            {
               assert(false); // the Entity expression should have matched one of the above
            }

            // copy any leading characters that don't need to be escaped
            entity.MatchString(&destination,8);

         }
         if (!matchedOnce)
         {
            // there were no entities, so just copy the content.
            destination.append(source);
         }
         
         resultOk = true;
      }
      else
      {
         // UtlString capacity failed
         assert(false);
      }
   }
   else
   {
      resultOk = true; // empty source - easy
   }

   return resultOk;
}