summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean-Philippe Lang <jp_lang@yahoo.fr>2007-09-01 20:17:45 +0000
committerJean-Philippe Lang <jp_lang@yahoo.fr>2007-09-01 20:17:45 +0000
commit521f4a6ddbc9eebe9ee6347a677f8d1a0ea6790f (patch)
treedf488bf993181d91f76e5d6fa0dce19c62ea1438
parent296b6aee5aac812d35bc32eaab246f33574d30e0 (diff)
downloadredmine-521f4a6ddbc9eebe9ee6347a677f8d1a0ea6790f.tar.gz
redmine-521f4a6ddbc9eebe9ee6347a677f8d1a0ea6790f.zip
Fixed: auto-generated links corrupted when url contains & characters in the query string.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@690 e93f8b46-1217-0410-a6f0-8f06a7374b81
-rw-r--r--app/helpers/application_helper.rb2
1 files changed, 1 insertions, 1 deletions
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 550ce3c59..93f319997 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -177,7 +177,7 @@ module ApplicationHelper
# finally textilize text
@do_textilize ||= (Setting.text_formatting == 'textile') && (ActionView::Helpers::TextHelper.method_defined? "textilize")
- text = @do_textilize ? auto_link(RedCloth.new(text, [:hard_breaks]).to_html) : simple_format(auto_link(h(text)))
+ text = @do_textilize ? RedCloth.new(auto_link(text), [:hard_breaks]).to_html : simple_format(auto_link(h(text)))
end
# Same as Rails' simple_format helper without using paragraphs
id='n9' href='#n9'>9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
/*
 * Copyright 2000-2014 Vaadin Ltd.
 * 
 * Licensed 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 com.vaadin.server;

import java.util.Collections;
import java.util.Set;

import com.vaadin.shared.ApplicationConstants;
import com.vaadin.shared.ui.BrowserWindowOpenerState;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.UI;

/**
 * Component extension that opens a browser popup window when the extended
 * component is clicked.
 * 
 * @author Vaadin Ltd
 * @since 7.0.0
 */
public class BrowserWindowOpener extends AbstractExtension {

    private static class BrowserWindowOpenerUIProvider extends UIProvider {

        private final String path;
        private final Class<? extends UI> uiClass;

        public BrowserWindowOpenerUIProvider(Class<? extends UI> uiClass,
                String path) {
            this.path = ensureInitialSlash(path);
            this.uiClass = uiClass;
        }

        private static String ensureInitialSlash(String path) {
            if (path == null) {
                return null;
            } else if (!path.startsWith("/")) {
                return '/' + path;
            } else {
                return path;
            }
        }

        @Override
        public Class<? extends UI> getUIClass(UIClassSelectionEvent event) {
            String requestPathInfo = event.getRequest().getPathInfo();
            if (path.equals(requestPathInfo)) {
                return uiClass;
            } else {
                return null;
            }
        }
    }

    private final BrowserWindowOpenerUIProvider uiProvider;

    /**
     * Creates a window opener that will open windows containing the provided UI
     * class
     * 
     * @param uiClass
     *            the UI class that should be opened when the extended component
     *            is clicked
     */
    public BrowserWindowOpener(Class<? extends UI> uiClass) {
        this(uiClass, generateUIClassUrl(uiClass));
    }

    /**
     * Creates a window opener that will open windows containing the provided UI
     * using the provided path
     * 
     * @param uiClass
     *            the UI class that should be opened when the extended component
     *            is clicked
     * @param path
     *            the path that the UI should be bound to
     */
    public BrowserWindowOpener(Class<? extends UI> uiClass, String path) {
        // Create a Resource with a translated URL going to the VaadinService
        this(new ExternalResource(ApplicationConstants.APP_PROTOCOL_PREFIX
                + path), new BrowserWindowOpenerUIProvider(uiClass, path));
    }

    /**
     * Creates a window opener that will open windows to the provided URL
     * 
     * @param url
     *            the URL to open in the window
     */
    public BrowserWindowOpener(String url) {
        this(new ExternalResource(url));
    }

    /**
     * Creates a window opener that will open window to the provided resource
     * 
     * @param resource
     *            the resource to open in the window
     */
    public BrowserWindowOpener(Resource resource) {
        this(resource, null);
    }

    private BrowserWindowOpener(Resource resource,
            BrowserWindowOpenerUIProvider uiProvider) {
        this.uiProvider = uiProvider;
        setResource(BrowserWindowOpenerState.locationResource, resource);
    }

    public void extend(AbstractComponent target) {
        super.extend(target);
    }

    /**
     * Sets the provided URL {@code url} for this instance. The {@code url} will
     * be opened in a new browser window/tab when the extended component is
     * clicked.
     * 
     * @since 7.4
     * 
     * @param url
     *            URL to open
     */
    public void setUrl(String url) {
        setResource(new ExternalResource(url));
    }

    /**
     * Sets the provided {@code resource} for this instance. The
     * {@code resource} will be opened in a new browser window/tab when the
     * extended component is clicked.
     * 
     * @since 7.4
     * 
     * @param resource
     *            resource to open
     */
    public void setResource(Resource resource) {
        setResource(BrowserWindowOpenerState.locationResource, resource);
    }

    /**
     * Returns the resource for this instance.
     * 
     * @since 7.4
     * 
     * @return resource to open browser window
     */
    public Resource getResource() {
        return getResource(BrowserWindowOpenerState.locationResource);
    }

    /**
     * Returns the URL for this BrowserWindowOpener instance. Returns
     * {@code null} if this instance is not URL resource based (a non URL based
     * resource has been set for it).
     * 
     * @since 7.4
     * 
     * @return URL to open in the new browser window/tab when the extended
     *         component is clicked
     */
    public String getUrl() {
        Resource resource = getResource();
        if (resource instanceof ExternalResource) {
            return ((ExternalResource) resource).getURL();
        }
        return null;
    }

    /**
     * Sets the target window name that will be used. If a window has already
     * been opened with the same name, the contents of that window will be
     * replaced instead of opening a new window. If the name is
     * <code>null</code> or <code>"_blank"</code>, a new window will always be
     * opened.
     * 
     * @param windowName
     *            the target name for the window
     */
    public void setWindowName(String windowName) {
        getState().target = windowName;
    }

    /**
     * Gets the target window name.
     * 
     * @see #setWindowName(String)
     * 
     * @return the window target string
     */
    public String getWindowName() {
        return getState(false).target;
    }

    // Avoid breaking url to multiple lines
    // @formatter:off 
    /**
     * Sets the features for opening the window. See e.g.
     * {@link https://developer.mozilla.org/en-US/docs/DOM/window.open#Position_and_size_features}
     * for a description of the commonly supported features.
     * 
     * @param features a string with window features, or <code>null</code> to use the default features.
     */
    // @formatter:on
    public void setFeatures(String features) {
        getState().features = features;
    }

    /**
     * Gets the window features.
     * 
     * @see #setFeatures(String)
     * @return
     */
    public String getFeatures() {
        return getState(false).features;
    }

    @Override
    protected BrowserWindowOpenerState getState() {
        return (BrowserWindowOpenerState) super.getState();
    }

    @Override
    protected BrowserWindowOpenerState getState(boolean markAsDirty) {
        return (BrowserWindowOpenerState) super.getState(markAsDirty);
    }

    @Override
    public void attach() {
        super.attach();
        if (uiProvider != null
                && !getSession().getUIProviders().contains(uiProvider)) {
            getSession().addUIProvider(uiProvider);
        }
    }

    @Override
    public void detach() {
        if (uiProvider != null) {
            getSession().removeUIProvider(uiProvider);
        }
        super.detach();
    }

    private static String generateUIClassUrl(Class<? extends UI> uiClass) {
        return "popup/" + uiClass.getSimpleName();
    }

    /**
     * Sets a URI fragment that will be added to the URI opened in the window.
     * If the window is opened to contain a Vaadin UI, the fragment will be
     * available using {@link Page#getUriFragment()} on the Page instance of the
     * new UI.
     * <p>
     * The default value is <code>null</code>.
     * 
     * @param uriFragment
     *            the URI fragment string that should be included in the opened
     *            URI, or <code>null</code> to preserve the original fragment of
     *            the URI.
     */
    public void setUriFragment(String uriFragment) {
        getState().uriFragment = uriFragment;
    }

    /**
     * Gets that URI fragment configured for opened windows.
     * 
     * @return the URI fragment string, or <code>null</code> if no fragment is
     *         configured.
     * 
     * @see #setUriFragment(String)
     */
    public String getUriFragment() {
        return getState(false).uriFragment;
    }

    /**
     * Sets a parameter that will be added to the query string of the opened
     * URI. If the window is opened to contain a Vaadin UI, the parameter will
     * be available using {@link VaadinRequest#getParameter(String)} e.g. using
     * the request instance passed to {@link UI#init(VaadinRequest)}.
     * <p>
     * Setting a parameter with the same name as a previously set parameter will
     * replace the previous value.
     * 
     * @param name
     *            the name of the parameter to add, not <code>null</code>
     * @param value
     *            the value of the parameter to add, not <code>null</code>
     * 
     * @see #removeParameter(String)
     * @see #getParameterNames()
     * @see #getParameter(String)
     */
    public void setParameter(String name, String value) {
        if (name == null || value == null) {
            throw new IllegalArgumentException("Null not allowed");
        }
        getState().parameters.put(name, value);
    }

    /**
     * Removes a parameter that has been set using
     * {@link #setParameter(String, String)}. Removing a parameter that has not
     * been set has no effect.
     * 
     * @param name
     *            the name of the parameter to remove, not <code>null</code>
     * 
     * @see #setParameter(String, String)
     */
    public void removeParameter(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Null not allowed");
        }
        getState().parameters.remove(name);
    }

    /**
     * Gets the names of all parameters set using
     * {@link #setParameter(String, String)}.
     * 
     * @return an unmodifiable set of parameter names
     * 
     * @see #setParameter(String, String)
     * @see #getParameter(String)
     */
    public Set<String> getParameterNames() {
        return Collections.unmodifiableSet(getState().parameters.keySet());
    }

    /**
     * Gets the value of a parameter set using
     * {@link #setParameter(String, String)}. If there is no parameter with the
     * given name, <code>null</code> is returned.
     * 
     * @param name
     *            the name of the parameter to get, not <code>null</code>
     * @return the value of the parameter, or <code>null</code> there is no
     *         parameter
     * 
     * @see #setParameter(String, String)
     * @see #getParameter(String)
     */
    public String getParameter(String name) {
        if (name == null) {
            throw new IllegalArgumentException("Null not allowed");
        }
        return getState(false).parameters.get(name);
    }

}