diff options
author | Julien Lancelot <julien.lancelot@sonarsource.com> | 2014-01-30 16:30:37 +0100 |
---|---|---|
committer | Julien Lancelot <julien.lancelot@sonarsource.com> | 2014-01-30 16:30:37 +0100 |
commit | 9bba8b928d84ac3eab8a0ae4172d1bd77bade3ea (patch) | |
tree | e98b97a96d1abe4b60c29b352726cf42f8a4eb81 /sonar-core/src | |
parent | fae04901b7d9d48306c3e2dd66f264b3ef21ce0b (diff) | |
download | sonarqube-9bba8b928d84ac3eab8a0ae4172d1bd77bade3ea.tar.gz sonarqube-9bba8b928d84ac3eab8a0ae4172d1bd77bade3ea.zip |
SONAR-4796 '%' and '_' should be escaped in Name/Key field of the Measures page
Diffstat (limited to 'sonar-core/src')
3 files changed, 106 insertions, 4 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java index 23906534131..3033275c5fe 100644 --- a/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java +++ b/sonar-core/src/main/java/org/sonar/core/measure/MeasureFilterSql.java @@ -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(); diff --git a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterExecutorTest.java b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterExecutorTest.java index 26e1a3c1e5f..99947e58009 100644 --- a/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterExecutorTest.java +++ b/sonar-core/src/test/java/org/sonar/core/measure/MeasureFilterExecutorTest.java @@ -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 index 00000000000..9b8d393278e --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/measure/MeasureFilterExecutorTest/escape_percent_and_underscore_when_filter_by_component_name_or_key.xml @@ -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> |