]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-4796 '%' and '_' should be escaped in Name/Key field of the Measures page
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 30 Jan 2014 15:30:37 +0000 (16:30 +0100)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Thu, 30 Jan 2014 15:30:37 +0000 (16:30 +0100)
sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java
sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterExecutorTest.java
sonar-core/src/test/resources/org/sonar/core/measure/MeasureFilterExecutorTest/escape_percent_and_underscore_when_filter_by_component_name_or_key.xml [new file with mode: 0644]

index 23906534131ebcfe83ac24409c98b1275ba2c670..3033275c5fe296a9f1b49ee2d6dde659a5e5d55d 100644 (file)
@@ -27,9 +27,12 @@ import org.apache.commons.dbutils.DbUtils;
 import org.apache.commons.lang.StringEscapeUtils;
 import org.apache.commons.lang.StringUtils;
 import org.sonar.core.persistence.Database;
+import org.sonar.core.persistence.dialect.MsSql;
+import org.sonar.core.persistence.dialect.Oracle;
 import org.sonar.core.resource.SnapshotDto;
 
 import javax.annotation.Nullable;
+
 import java.sql.*;
 import java.util.Comparator;
 import java.util.List;
@@ -163,16 +166,18 @@ class MeasureFilterSql {
   private void appendResourceKeyCondition(StringBuilder sb) {
     if (StringUtils.isNotBlank(filter.getResourceKey())) {
       sb.append(" AND UPPER(p.kee) LIKE '%");
-      sb.append(StringEscapeUtils.escapeSql(StringUtils.upperCase(filter.getResourceKey())));
+      sb.append(escapePercentAndUnderscrore(StringEscapeUtils.escapeSql(StringUtils.upperCase(filter.getResourceKey()))));
       sb.append("%'");
+      appendEscapeForSomeDb(sb);
     }
   }
 
   private void appendResourceNameCondition(StringBuilder sb) {
     if (StringUtils.isNotBlank(filter.getResourceName())) {
       sb.append(" AND s.project_id IN (SELECT rindex.resource_id FROM resource_index rindex WHERE rindex.kee LIKE '");
-      sb.append(StringEscapeUtils.escapeSql(StringUtils.lowerCase(filter.getResourceName())));
+      sb.append(escapePercentAndUnderscrore(StringEscapeUtils.escapeSql(StringUtils.lowerCase(filter.getResourceName()))));
       sb.append("%'");
+      appendEscapeForSomeDb(sb);
       if (!filter.getResourceQualifiers().isEmpty()) {
         sb.append(" AND rindex.qualifier IN ");
         appendInStatement(filter.getResourceQualifiers(), sb);
@@ -214,6 +219,19 @@ class MeasureFilterSql {
     to.append(") ");
   }
 
+  /**
+   * Replace escape percent and underscore by adding a slash just before
+   */
+  private String escapePercentAndUnderscrore(String value){
+    return value.replaceAll("%", "\\\\%").replaceAll("_", "\\\\_");
+  }
+
+  private void appendEscapeForSomeDb(StringBuilder sb){
+    if (database.getDialect().getId().equals(Oracle.ID) || database.getDialect().getId().equals(MsSql.ID)) {
+      sb.append(" ESCAPE '\\'");
+    }
+  }
+
   abstract static class RowProcessor {
     abstract Function sortFieldFunction();
 
index 26e1a3c1e5f23139abd32d9fe338eeeecd80cf26..99947e5800962d2f1b769871533faaf3ca4dc87a 100644 (file)
@@ -33,6 +33,7 @@ import java.sql.SQLException;
 import java.util.Arrays;
 import java.util.List;
 
+import static com.google.common.collect.Lists.newArrayList;
 import static org.fest.assertions.Assertions.assertThat;
 
 public class MeasureFilterExecutorTest {
@@ -462,7 +463,7 @@ public class MeasureFilterExecutorTest {
   }
 
   @Test
-  public void filter_by_resource_name() throws SQLException {
+  public void filter_by_component_name() throws SQLException {
     db.prepareDbUnit(getClass(), "shared.xml");
     MeasureFilter filter = new MeasureFilter().setResourceQualifiers(Arrays.asList("TRK")).setResourceName("PHP Proj");
     List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
@@ -472,7 +473,7 @@ public class MeasureFilterExecutorTest {
   }
 
   @Test
-  public void filter_by_resource_key() throws SQLException {
+  public void filter_by_component_key() throws SQLException {
     db.prepareDbUnit(getClass(), "shared.xml");
     MeasureFilter filter = new MeasureFilter().setResourceQualifiers(Arrays.asList("TRK")).setResourceKey("Va_proje");
     List<MeasureFilterRow> rows = executor.execute(filter, new MeasureFilterContext());
@@ -494,6 +495,22 @@ public class MeasureFilterExecutorTest {
     verifyJavaBigFile(rows.get(0));
   }
 
+  /**
+   * see SONAR-4796
+   */
+  @Test
+  public void escape_percent_and_underscore_when_filter_by_component_name_or_key() throws SQLException {
+    db.prepareDbUnit(getClass(), "escape_percent_and_underscore_when_filter_by_component_name_or_key.xml");
+
+    assertThat(executor.execute(
+      new MeasureFilter().setResourceQualifiers(newArrayList("CLA")).setResourceKey("java_"),
+      new MeasureFilterContext())).hasSize(2);
+
+    assertThat(executor.execute(
+      new MeasureFilter().setResourceQualifiers(newArrayList("CLA")).setResourceName("java%"),
+      new MeasureFilterContext())).hasSize(2);
+  }
+
   @Test
   public void filter_by_base_resource() throws SQLException {
     db.prepareDbUnit(getClass(), "shared.xml");
diff --git a/sonar-core/src/test/resources/org/sonar/core/measure/MeasureFilterExecutorTest/escape_percent_and_underscore_when_filter_by_component_name_or_key.xml b/sonar-core/src/test/resources/org/sonar/core/measure/MeasureFilterExecutorTest/escape_percent_and_underscore_when_filter_by_component_name_or_key.xml
new file mode 100644 (file)
index 0000000..9b8d393
--- /dev/null
@@ -0,0 +1,67 @@
+<dataset>
+
+  <!-- java project -->
+  <projects kee="java_project:org.sonar.bar" long_name="org.sonar.bar" scope="FIL" qualifier="CLA" name="org.sonar.bar"
+            id="1" root_id="[null]"
+            description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"
+            created_at="2008-12-19 00:00:00.00"/>
+
+  <projects kee="java_project:org.sonar.foo" scope="FIL" qualifier="CLA" long_name="org.sonar.foo" name="org.sonar.foo"
+            id="2" root_id="1"
+            description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"
+            created_at="2008-12-19 00:00:00.00"/>
+
+  <projects kee="java project:org.sonar.foo.Big" scope="FIL" qualifier="CLA" long_name="org.sonar.foo.Big"
+            name="Big"
+            id="3" root_id="1"
+            description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"
+            created_at="2008-12-19 00:00:00.00"/>
+
+  <projects kee="java project:org.sonar.foo.Tiny" scope="FIL" qualifier="CLA" long_name="org.sonar.foo.Tiny" name="Tiny"
+            id="4" root_id="1"
+            description="[null]" enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"
+            created_at="2008-12-19 00:00:00.00"/>
+
+  <snapshots id="101" project_id="1" root_project_id="1" root_snapshot_id="[null]" parent_snapshot_id="[null]"
+             scope="FIL" qualifier="CLA" path="" depth="0"
+             purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+             period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]"
+             period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]"
+             period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+             created_at="2008-12-20 00:00:00.00" build_date="2008-12-20 00:00:00.00"
+             version="1.0" status="P" islast="[true]"/>
+
+  <snapshots id="102" project_id="2" root_project_id="1" root_snapshot_id="101" parent_snapshot_id="101"
+             scope="FIL" qualifier="CLA" path="101." depth="1"
+             purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+             period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]"
+             period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]"
+             period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+             created_at="2008-12-20 00:00:00.00" build_date="2008-12-20 00:00:00.00"
+             version="1.0" status="P" islast="[true]"/>
+
+  <snapshots id="103" project_id="3" root_project_id="1" root_snapshot_id="101" parent_snapshot_id="102"
+             scope="FIL" qualifier="CLA" path="101.102." depth="2"
+             purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+             period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]"
+             period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]"
+             period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+             created_at="2008-12-20 00:00:00.00" build_date="2008-12-20 00:00:00.00"
+             version="1.0" status="P" islast="[true]"/>
+
+  <snapshots id="104" project_id="4" root_project_id="1" root_snapshot_id="101" parent_snapshot_id="102"
+             scope="FIL" qualifier="CLA" path="101.102." depth="2"
+             purge_status="[null]" period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+             period2_mode="[null]" period2_param="[null]" period2_date="[null]" period3_mode="[null]"
+             period3_param="[null]" period3_date="[null]" period4_mode="[null]" period4_param="[null]"
+             period4_date="[null]" period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+             created_at="2008-12-20 00:00:00.00" build_date="2008-12-20 00:00:00.00"
+             version="1.0" status="P" islast="[true]"/>
+
+  <resource_index id="1" kee="java class1" position="0" name_size="12" resource_id="1" root_project_id="1" qualifier="CLA"/>
+  <resource_index id="2" kee="java class2" position="1" name_size="12" resource_id="2" root_project_id="1" qualifier="CLA"/>
+  <resource_index id="3" kee="java%class3" position="2" name_size="12" resource_id="3" root_project_id="1" qualifier="CLA"/>
+  <resource_index id="4" kee="java%class4" position="3" name_size="12" resource_id="4" root_project_id="1" qualifier="CLA"/>
+
+
+</dataset>