You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lo...@apache.org on 2020/03/26 16:42:50 UTC

[myfaces-tobago] branch tobago-4.x updated: TOBAGO-2023: An anchor href with mailto: entry must not use + to escape spaces

This is an automated email from the ASF dual-hosted git repository.

lofwyr pushed a commit to branch tobago-4.x
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git


The following commit(s) were added to refs/heads/tobago-4.x by this push:
     new d348c44  TOBAGO-2023: An anchor href with mailto: entry must not use + to escape spaces
d348c44 is described below

commit d348c44bc6fed376ab436870f43812c5fa1f2d96
Author: Udo Schnurpfeil <ud...@irian.eu>
AuthorDate: Thu Mar 26 17:39:54 2020 +0100

    TOBAGO-2023: An anchor href with mailto: entry must not use + to escape spaces
    
    * replace for "name" and "value": "+" (was space) to %20 (means also space)
    * UnitTest
    * close buttons
    * remove workaround from demo.js
    * Required parameters for tc:operation
---
 .../taglib/component/OperationTagDeclaration.java  |  4 +-
 .../myfaces/tobago/internal/util/RenderUtils.java  | 30 +++++++----
 .../tobago/internal/util/RenderUtilsUnitTest.java  | 61 ++++++++++++++++++++++
 .../90-release-checklist/release-checklist.xhtml   | 24 +++++++--
 .../src/main/webapp/script/demo.js                 | 12 -----
 5 files changed, 103 insertions(+), 28 deletions(-)

diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OperationTagDeclaration.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OperationTagDeclaration.java
index 476b5a4..f44824a 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OperationTagDeclaration.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OperationTagDeclaration.java
@@ -46,14 +46,14 @@ public interface OperationTagDeclaration {
   /**
    * Name of the operation to be executed.
    */
-  @TagAttribute()
+  @TagAttribute(required = true)
   @UIComponentTagAttribute()
   void setName(String name);
 
   /**
    * The id of the component the operation is related to.
    */
-  @TagAttribute()
+  @TagAttribute(required = true)
   @UIComponentTagAttribute()
   void setFor(String forAttribute);
 
diff --git a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java
index 3fbcf33..e28b2fa 100644
--- a/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java
+++ b/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java
@@ -258,6 +258,7 @@ public final class RenderUtils {
     }
 
     if (link != null || outcome != null) {
+      final String characterEncoding = facesContext.getResponseWriter().getCharacterEncoding();
       final StringBuilder builder = new StringBuilder(url);
       boolean firstParameter = !url.contains("?");
       for (final UIComponent child : component.getChildren()) {
@@ -269,23 +270,16 @@ public final class RenderUtils {
           } else {
             builder.append("&");
           }
-          builder.append(parameter.getName());
+          appendUrlEncoded(builder, parameter.getName(), characterEncoding);
           builder.append("=");
-          final Object value = parameter.getValue();
-          if (value != null) {
-            final String characterEncoding = facesContext.getResponseWriter().getCharacterEncoding();
-            try {
-              builder.append(URLEncoder.encode(value.toString(), characterEncoding));
-            } catch (final UnsupportedEncodingException e) {
-              LOG.error("", e);
-            }
-          }
+          appendUrlEncoded(builder, parameter.getValue(), characterEncoding);
         }
       }
 
       final String fragment = component.getFragment();
       if (StringUtils.isNotBlank(fragment)) {
-        builder.append("#").append(fragment.trim());
+        builder.append("#");
+        appendUrlEncoded(builder, fragment.trim(), characterEncoding);
       }
 
       url = builder.toString();
@@ -294,6 +288,20 @@ public final class RenderUtils {
     return url;
   }
 
+  private static void appendUrlEncoded(
+      final StringBuilder builder, final Object value, final String characterEncoding) {
+
+    if (value != null) {
+      try {
+        final String encode = URLEncoder.encode(value.toString(), characterEncoding);
+        // URLEncoder.encode may return + instead of %20 for a space, but this is not good in some cases, e.g. mailto:
+        builder.append(encode.replace("+", "%20"));
+      } catch (final UnsupportedEncodingException e) {
+        LOG.error("string='" + value + "'", e);
+      }
+    }
+  }
+
   public static CommandMap getBehaviorCommands(final FacesContext facesContext,
       final ClientBehaviorHolder clientBehaviorHolder) {
     CommandMap commandMap = null;
diff --git a/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/RenderUtilsUnitTest.java b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/RenderUtilsUnitTest.java
new file mode 100644
index 0000000..c2d6010
--- /dev/null
+++ b/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/RenderUtilsUnitTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.myfaces.tobago.component.UILink;
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.faces.component.UIParameter;
+
+public class RenderUtilsUnitTest extends AbstractTobagoTestBase {
+
+  @Test
+  public void simple() {
+    final UILink link = new UILink();
+    link.setLink("local.xhtml");
+    final String url = RenderUtils.generateUrl(getFacesContext(), link);
+    Assert.assertEquals("local.xhtml", url);
+  }
+
+  @Test
+  public void mailto() {
+    final UILink link = new UILink();
+    link.setLink("mailto:MyFaces Discussion <us...@myfaces.apache.org>");
+
+    final UIParameter subject = new UIParameter();
+    subject.setName("subject");
+    subject.setValue("[Tobago] Preparation for the 5.0.0 release");
+    link.getChildren().add(subject);
+
+    final UIParameter body = new UIParameter();
+    body.setName("body");
+    body.setValue("Hi, folks,\n"
+        + "\n"
+          + "we plan to build version 5.0.0 of Tobago soon.");
+    link.getChildren().add(body);
+
+    final String url = RenderUtils.generateUrl(getFacesContext(), link);
+    Assert.assertEquals("mailto:MyFaces Discussion <us...@myfaces.apache.org>"
+        + "?subject=%5BTobago%5D%20Preparation%20for%20the%205.0.0%20release"
+        + "&body=Hi%2C%20folks%2C%0A%0Awe%20plan%20to%20build%20version%205.0.0%20of%20Tobago%20soon.", url);
+  }
+}
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/90-release-checklist/release-checklist.xhtml b/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/90-release-checklist/release-checklist.xhtml
index b9fbe60..e080dc8 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/90-release-checklist/release-checklist.xhtml
+++ b/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/90-release-checklist/release-checklist.xhtml
@@ -30,7 +30,7 @@
     <tc:section label="Step by Step">
 
       Checklist of tasks to perform for each release. For general information about Apache releases you may also consult
-      <tc:link label="Publishing Maven Artifacts" link="http://www.apache.org/dev/publishing-maven-artifacts.html"
+      <tc:link label="Publishing Maven Releases" link="http://infra.apache.org/maven-releases.html"
                image="fa-external-link"/>.
 
       <tc:section label="Preparation">
@@ -45,8 +45,11 @@
 
           <li>Ensure that all open bugs and issues in
             <tc:link label="Jira"
-                     link="https://issues.apache.org/jira/issues/?jql=project%20%3D%20TOBAGO%20AND%20fixVersion%20%3D%20#{apiController.releases[0].version}"
-                     image="fa-external-link"/> have been either fixed
+                     link="https://issues.apache.org/jira/issues/"
+                     image="fa-external-link">
+              <f:param name="jql" value="project = TOBAGO AND fixVersion = #{apiController.releases[0].version}"/>
+            </tc:link>
+            have been either fixed
             or moved to an other release version.
           </li>
 
@@ -63,6 +66,11 @@
             and ask for problems with the release candidate.
             <tc:popup markup="large" collapsedMode="hidden" id="preparation-email">
               <tc:box label="Preparation email">
+                <f:facet name="bar">
+                  <tc:button image="fa-close" tip="Close" omit="true">
+                    <tc:operation name="hide" for="preparation-email"/>
+                  </tc:button>
+                </f:facet>
                 <i>Replace the variable part &lt;sender-name></i>.
                 <tc:separator/>
                 <c:set var="subject" value="[Tobago] Preparation for the #{apiController.releases[0].version} release"/>
@@ -197,6 +205,11 @@ $ mvn release:perform
             </tc:link> with the staging location.
             <tc:popup markup="large" collapsedMode="hidden" id="vote-email">
               <tc:box label="Voting email">
+                <f:facet name="bar">
+                  <tc:button image="fa-close" tip="Close" omit="true">
+                    <tc:operation name="hide" for="vote-email"/>
+                  </tc:button>
+                </f:facet>
                 <i>Replace the variable part &lt;sender-name>, &lt;insert-list>, &lt;use-one-of>, &lt;a>, &lt;b>or, &lt;c>, &lt;id-from-nexus></i>.
                 <tc:separator/>
                 <c:set var="subject" value="[VOTE] Release Tobago #{apiController.releases[0].version}"/>
@@ -338,6 +351,11 @@ $ mvn site:stage -DstagingDirectory=$TOBAGO_SITE/tobago-publish</code></pre>
             </tc:link>.
             <tc:popup markup="large" collapsedMode="hidden" id="announcement-email">
               <tc:box label="Announcement email">
+                <f:facet name="bar">
+                  <tc:button image="fa-close" tip="Close" omit="true">
+                    <tc:operation name="hide" for="announcement-email"/>
+                  </tc:button>
+                </f:facet>
                 <i>Replace the variable parts &lt;edit-me></i>.
                 <tc:separator/>
                 <c:set var="subject" value="[ANNOUNCE] Apache Tobago #{apiController.releases[0].version} released"/>
diff --git a/tobago-example/tobago-example-demo/src/main/webapp/script/demo.js b/tobago-example/tobago-example-demo/src/main/webapp/script/demo.js
index b517830..08a5c84 100644
--- a/tobago-example/tobago-example-demo/src/main/webapp/script/demo.js
+++ b/tobago-example/tobago-example-demo/src/main/webapp/script/demo.js
@@ -120,15 +120,3 @@ Demo.initGoogleSearch = function () {
 
 Tobago.registerListener(Demo.initGoogleSearch, Tobago.Phase.DOCUMENT_READY);
 Tobago.registerListener(Demo.initGoogleSearch, Tobago.Phase.AFTER_UPDATE);
-
-Demo.initMailTo = function () {
-  var $command = jQuery("[href^=mailto]");
-  $command.each(function() {
-    var $this = jQuery(this);
-    // this is, to fix URL encoded spaces
-    $this.attr("href", $this.attr("href").replace(/\+/g, "%20"));
-  });
-};
-
-Tobago.registerListener(Demo.initMailTo, Tobago.Phase.DOCUMENT_READY);
-Tobago.registerListener(Demo.initMailTo, Tobago.Phase.AFTER_UPDATE);