Repository: trafficserver
Updated Branches:
  refs/heads/master 6d4005f8b -> 38996681d


TS-2576: Add Oct/Hex escape representation into LogFormat

Introudce two escape representations into LogFormat:
* Oct escape sequence:
  '\abc': a,b,c should be one of [0-9], and
          (a*8^2 + b*8 + c) should be greater than 0 and less than 255.

* Hex escape sequence:
  '\xab': a,b should be one of [0-9, a-f, A-F], and
          (a*16 + b) should be greater than 0 and less than 255.

Signed-off-by: Yunkai Zhang <qiushu....@taobao.com>


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/38996681
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/38996681
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/38996681

Branch: refs/heads/master
Commit: 38996681d870249f923e07e5311f983372307316
Parents: 6d4005f
Author: Yunkai Zhang <qiushu....@taobao.com>
Authored: Tue Feb 18 18:26:20 2014 +0800
Committer: Yunkai Zhang <qiushu....@taobao.com>
Committed: Wed Feb 26 20:29:21 2014 +0800

----------------------------------------------------------------------
 CHANGES                    |   2 +
 proxy/logging/LogFormat.cc | 108 +++++++++++++++++++++++++++++++++++++---
 proxy/logging/LogFormat.h  |   1 +
 3 files changed, 103 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/38996681/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 150a243..5b374ec 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,8 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache Traffic Server 5.0.0
 
+  *) [TS-2576] Add Oct/Hex escape representation into LogFormat
+
   *) [TS-2494] fix the crash that return the stale cached document
    when os is down, even if it`s status is not 200 (ok).
   *) [TS-2590] Translate documentation into Japanese.

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/38996681/proxy/logging/LogFormat.cc
----------------------------------------------------------------------
diff --git a/proxy/logging/LogFormat.cc b/proxy/logging/LogFormat.cc
index 80e46f4..b5c50f3 100644
--- a/proxy/logging/LogFormat.cc
+++ b/proxy/logging/LogFormat.cc
@@ -555,6 +555,77 @@ LogFormat::parse_symbol_string(const char *symbol_string, 
LogFieldList *field_li
   return field_count;
 }
 
+//
+// Parse escape string, supports two forms:
+//
+// 1) Octal representation: '\abc', for example: '\060'
+//    0 < (a*8^2 + b*8 + c) < 255
+//
+// 2) Hex representation: '\xab', for exampe: '\x3A'
+//    0 < (a*16 + b) < 255
+//
+// Return -1 if the beginning four characters are not valid
+// escape sequence, otherwise reutrn unsigned char value of the
+// escape sequence in the string.
+//
+// NOTE: The value of escape sequence should be greater than 0
+//       and less than 255, since:
+//       - 0 is terminator of string, and
+//       - 255('\377') has been used as LOG_FIELD_MARKER.
+//
+int
+LogFormat::parse_escape_string(const char *str, int len)
+{
+  int sum, start = 0;
+  unsigned char a, b, c;
+
+  if (str[start] != '\\' || len < 2)
+    return -1;
+
+  if (str[start + 1] == '\\')
+    return '\\';
+
+  if (len < 4)
+    return -1;
+
+  a = (unsigned char)str[start + 1];
+  b = (unsigned char)str[start + 2];
+  c = (unsigned char)str[start + 3];
+
+  if (isdigit(a) && isdigit(b) && isdigit(b)) {
+
+    sum = (a - '0')*64 + (b - '0')*8 + (c - '0');
+
+    if (sum == 0 || sum >= 255) {
+      Warning("Octal escape sequence out of range: \\%c%c%c, treat it as 
normal string\n", a, b, c);
+      return -1;
+    } else
+      return sum;
+
+  } else if (tolower(a) == 'x' && isxdigit(b) && isxdigit(c)) {
+    int i, j;
+    if (isdigit(b))
+      i = b - '0';
+    else
+      i = toupper(b) - 'A' + 10;
+
+    if (isdigit(c))
+      j = c - '0';
+    else
+      j = toupper(c) - 'A' + 10;
+
+    sum = i*16 + j;
+
+    if (sum == 0 || sum >= 255) {
+      Warning("Hex escape sequence out of range: \\%c%c%c, treat it as normal 
string\n", a, b, c);
+      return -1;
+    } else
+      return sum;
+  }
+
+  return -1;
+}
+
 /*-------------------------------------------------------------------------
   LogFormat::parse_format_string
 
@@ -594,6 +665,7 @@ LogFormat::parse_format_string(const char *format_str, char 
**printf_str, char *
   unsigned field_count = 0;
   unsigned field_len;
   unsigned start, stop;
+  int escape_char;
 
   for (start = 0; start < len; start++) {
     //
@@ -623,21 +695,41 @@ LogFormat::parse_format_string(const char *format_str, 
char **printf_str, char *
         fields_pos += field_len;
         (*printf_str)[printf_pos++] = LOG_FIELD_MARKER;
         ++field_count;
+        start = stop;
       } else {
         //
-        // This was not a logging field spec after all, so copy it
-        // over to the printf string as is.
+        // This was not a logging field spec after all,
+        // then try to detect and parse escape string.
         //
-        memcpy(&(*printf_str)[printf_pos], &format_str[start], stop - start + 
1);
-        printf_pos += stop - start + 1;
+        escape_char = parse_escape_string(&format_str[start], (len - start));
+
+        if (escape_char == '\\') {
+          start += 1;
+          (*printf_str)[printf_pos++] = (char)escape_char;
+        } else if (escape_char >= 0) {
+          start += 3;
+          (*printf_str)[printf_pos++] = (char)escape_char;
+        } else {
+          memcpy(&(*printf_str)[printf_pos], &format_str[start], stop - start 
+ 1);
+          printf_pos += stop - start + 1;
+        }
       }
-      start = stop;
     } else {
       //
-      // This was not the start of a logging field spec, so simply
-      // put this char into the printf_str.
+      // This was not the start of a logging field spec,
+      // then try to detect and parse escape string.
       //
-      (*printf_str)[printf_pos++] = format_str[start];
+      escape_char = parse_escape_string(&format_str[start], (len - start));
+
+      if (escape_char == '\\') {
+        start += 1;
+        (*printf_str)[printf_pos++] = (char)escape_char;
+      } else if (escape_char >= 0) {
+        start += 3;
+        (*printf_str)[printf_pos++] = (char)escape_char;
+      } else {
+        (*printf_str)[printf_pos++] = format_str[start];
+      }
     }
   }
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/38996681/proxy/logging/LogFormat.h
----------------------------------------------------------------------
diff --git a/proxy/logging/LogFormat.h b/proxy/logging/LogFormat.h
index da32018..fcc2cef 100644
--- a/proxy/logging/LogFormat.h
+++ b/proxy/logging/LogFormat.h
@@ -83,6 +83,7 @@ public:
                                               char **file_name, char 
**file_header, LogFileFormat * file_type);
   static int parse_symbol_string(const char *symbol_string, LogFieldList 
*field_list, bool *contains_aggregates);
   static int parse_format_string(const char *format_str, char **printf_str, 
char **fields_str);
+  static int parse_escape_string(const char *str, int len);
 
   // these are static because m_tagging_on is a class variable
   static void turn_tagging_on() { m_tagging_on = true; }

Reply via email to