github-advanced-security[bot] commented on code in PR #596:
URL: https://github.com/apache/jspwiki/pull/596#discussion_r4524755832


##########
jspwiki-main/src/main/java/org/apache/wiki/plugin/LanguagePlugin.java:
##########
@@ -0,0 +1,158 @@
+/*
+    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.wiki.plugin;
+
+import org.apache.wiki.api.core.Context;
+import org.apache.wiki.api.exceptions.PluginException;
+import org.apache.wiki.api.plugin.Plugin;
+import org.apache.wiki.render.RenderingManager;
+
+import jakarta.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Shows the content that matches the language preference of the visitor, as 
the browser sends it in the {@code Accept-Language}
+ * header. The body holds one block per language, written as {@code 
:xx:text::} with the language code between colons, and an optional
+ * {@code :else:text::} block for visitors that none of the blocks suits:
+ *
+ * <pre>
+ * [{LanguagePlugin
+ *
+ * :de:Willkommen::  :en:Welcome::  :else:Welcome / Willkommen::}]
+ * </pre>
+ *
+ * <p>The languages of the visitor are tried in the order of their quality 
values, and a block matches when its code is the language of
+ * the tag, so {@code de} matches {@code de-AT}. Only the language is 
compared, not the region. If no block matches and there is no
+ * {@code :else:} block, nothing is shown. The text of the chosen block is 
rendered as wiki markup. A block ends at the first
+ * {@code ::}, so the text of a block cannot contain it.</p>
+ *
+ * <p>Parameters: none.</p>
+ *
+ * @since 3.0.1
+ */
+public class LanguagePlugin implements Plugin {
+
+    private static final Pattern BLOCK = Pattern.compile( 
":([a-zA-Z]{2,3}):(.*?)::", Pattern.DOTALL );
+    private static final Pattern ELSE_BLOCK = Pattern.compile( 
":else:(.*?)::", Pattern.DOTALL );
+
+    /** A language tag of the {@code Accept-Language} header with its quality 
value. */
+    private static final class Preference {
+        final String language;
+        final double quality;
+
+        Preference( final String language, final double quality ) {
+            this.language = language;
+            this.quality = quality;
+        }
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String getDisplayName( final Locale locale ) {
+        final ResourceBundle rb = ResourceBundle.getBundle( 
PluginManager.PLUGIN_I18N_RESOURCE, locale );
+        return rb.getString( this.getClass().getSimpleName() );
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String getSnipExample() {
+        return "LanguagePlugin\n\n:de:{text}::  :en:{text}::  
:else:{text}::\n";
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String execute( final Context context, final Map< String, String > 
params ) throws PluginException {
+        final String body = params.get( DefaultPluginManager.PARAM_BODY );
+        if( body == null || body.isEmpty() ) {
+            return "";
+        }
+        final HttpServletRequest request = context.getHttpRequest();
+        final String header = request == null ? null : request.getHeader( 
"Accept-Language" );
+        String text = null;
+        for( final String language : parse( header ) ) {
+            final Matcher blocks = BLOCK.matcher( body );
+            while( text == null && blocks.find() ) {
+                if( language.equalsIgnoreCase( blocks.group( 1 ) ) ) {
+                    text = blocks.group( 2 );
+                }
+            }
+            if( text != null ) {
+                break;
+            }
+        }
+        if( text == null ) {
+            final Matcher fallback = ELSE_BLOCK.matcher( body );

Review Comment:
   ## CodeQL / Polynomial regular expression used on uncontrolled data
   
   This [regular expression](1) that depends on a [user-provided value](2) may 
run slow on strings starting with ':else:' and with many repetitions of 
':else:a'.
   This [regular expression](1) that depends on a [user-provided value](3) may 
run slow on strings starting with ':else:' and with many repetitions of 
':else:a'.
   
   [Show more 
details](https://github.com/apache/jspwiki/security/code-scanning/38)



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to