View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.internal.impl;
20  
21  /**
22   * Sanitizes strings that may carry remote-derived bytes (artifact coordinates, checksum values, transfer error
23   * messages) before they are logged or persisted. Bytes received from a remote repository must not be able to
24   * influence terminal rendering: raw control characters such as ESC (ANSI escape sequences) or CR (line rewrite)
25   * embedded in, for example, a transitive POM's coordinates could otherwise erase or forge log lines - including
26   * the sole integrity WARNING emitted under the default "warn" checksum policy.
27   *
28   * @since 2.0.23
29   */
30  final class LogSanitizer {
31      private LogSanitizer() {}
32  
33      /**
34       * Replaces every ISO control character below U+0020 (except LF and TAB) as well as DEL (U+007F) with its
35       * visible {@code \}{@code uXXXX} escape, preserving the evidence while neutralizing terminal escape
36       * sequences. Returns the input instance unchanged (no allocation) when nothing needs escaping; returns
37       * {@code null} for {@code null} input.
38       */
39      static String sanitize(String value) {
40          if (value == null) {
41              return null;
42          }
43          StringBuilder result = null;
44          for (int i = 0; i < value.length(); i++) {
45              char c = value.charAt(i);
46              if ((c < 0x20 && c != '\n' && c != '\t') || c == 0x7f) {
47                  if (result == null) {
48                      result = new StringBuilder(value.length() + 16);
49                      result.append(value, 0, i);
50                  }
51                  result.append(String.format("\\u%04X", (int) c));
52              } else if (result != null) {
53                  result.append(c);
54              }
55          }
56          return result == null ? value : result.toString();
57      }
58  }