1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.wysiwyg.server.script

File DefaultWysiwygEditorScriptService.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart5.png
74% of files have more coverage

Code metrics

8
43
7
1
220
125
15
0.35
6.14
7
2.14

Classes

Class Line # Actions
DefaultWysiwygEditorScriptService 52 43 0% 15 31
0.4655172546.6%
 

Contributing tests

No tests hitting this source file were found.

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.wysiwyg.server.script;
21   
22    import javax.inject.Inject;
23    import javax.inject.Named;
24    import javax.inject.Provider;
25    import javax.inject.Singleton;
26   
27    import org.slf4j.Logger;
28    import org.xwiki.component.annotation.Component;
29    import org.xwiki.component.manager.ComponentManager;
30    import org.xwiki.gwt.wysiwyg.client.converter.HTMLConverter;
31    import org.xwiki.model.reference.DocumentReference;
32    import org.xwiki.rendering.parser.Parser;
33    import org.xwiki.rendering.renderer.PrintRendererFactory;
34    import org.xwiki.rendering.syntax.Syntax;
35    import org.xwiki.security.authorization.ContextualAuthorizationManager;
36    import org.xwiki.security.authorization.Right;
37    import org.xwiki.wysiwyg.server.WysiwygEditorConfiguration;
38    import org.xwiki.wysiwyg.server.WysiwygEditorScriptService;
39   
40    import com.xpn.xwiki.XWikiContext;
41    import com.xpn.xwiki.XWikiException;
42    import com.xpn.xwiki.doc.XWikiDocument;
43   
44    /**
45    * Default implementation of {@link WysiwygEditorScriptService}.
46    *
47    * @version $Id: f5c7a37a3c04d7e0436253faee399e4be2744fcb $
48    */
49    @Component
50    @Named("wysiwyg")
51    @Singleton
 
52    public class DefaultWysiwygEditorScriptService implements WysiwygEditorScriptService
53    {
54    /**
55    * The context property which indicates if the current code was called from a template (only Velocity execution) or
56    * from a wiki page (wiki syntax rendering).
57    *
58    * @see #parseAndRender(String, String)
59    */
60    private static final String IS_IN_RENDERING_ENGINE = "isInRenderingEngine";
61   
62    @Inject
63    private Logger logger;
64   
65    /**
66    * The component manager. We need it because we have to access components dynamically.
67    */
68    @Inject
69    @Named("context")
70    private ComponentManager contextComponentManager;
71   
72    @Inject
73    private ContextualAuthorizationManager authorization;
74   
75    /**
76    * The component used to convert HTML to wiki syntax.
77    */
78    @Inject
79    private HTMLConverter htmlConverter;
80   
81    /**
82    * The component used to access the WYSIWYG editor configuration properties.
83    */
84    @Inject
85    private WysiwygEditorConfiguration editorConfiguration;
86   
87    @Inject
88    private Provider<XWikiContext> xcontextProvider;
89   
 
90  552 toggle @Override
91    public boolean isSyntaxSupported(String syntaxId)
92    {
93    // Special handling for XHTML since right the XHTML renderer doesn't produce valid XHTML. Thus if, for example,
94    // you the WYSIWYG editor and add 2 paragraphs, it'll generate {@code <p>a</p><p>b</p>} which is invalid XHTML
95    // and the page will fail to render.
96  552 if (syntaxId.equals(Syntax.XHTML_1_0.toIdString())) {
97  0 return false;
98    }
99   
100  552 try {
101  552 this.contextComponentManager.getInstance(Parser.class, syntaxId);
102  551 this.contextComponentManager.getInstance(PrintRendererFactory.class, syntaxId);
103  551 return true;
104    } catch (Exception e) {
105  1 return false;
106    }
107    }
108   
 
109  0 toggle @Override
110    public String parseAndRender(String html, String syntax)
111    {
112  0 XWikiDocument originalSecurityDocument = setSecurityDocument(createSecurityDocument());
113   
114    // Save the value of the "is in rendering engine" context property.
115  0 Object isInRenderingEngine = this.xcontextProvider.get().get(IS_IN_RENDERING_ENGINE);
116   
117  0 try {
118    // This tells display() methods that we are inside the rendering engine and thus that they can return wiki
119    // syntax and not HTML syntax (which is needed when outside the rendering engine, i.e. when we're inside
120    // templates using only Velocity for example).
121  0 this.xcontextProvider.get().put(IS_IN_RENDERING_ENGINE, true);
122   
123  0 return this.htmlConverter.parseAndRender(html, syntax);
124    } catch (Exception e) {
125    // Leave the previous HTML in case of an exception.
126  0 return html;
127    } finally {
128    // Restore the value of the value of the "is in rendering engine" context property.
129  0 if (isInRenderingEngine != null) {
130  0 this.xcontextProvider.get().put(IS_IN_RENDERING_ENGINE, isInRenderingEngine);
131    } else {
132  0 this.xcontextProvider.get().remove(IS_IN_RENDERING_ENGINE);
133    }
134   
135  0 setSecurityDocument(originalSecurityDocument);
136    }
137    }
138   
 
139  0 toggle @Override
140    public String render(DocumentReference templateReference)
141    {
142  0 if (!this.authorization.hasAccess(Right.VIEW, templateReference)) {
143  0 return null;
144    }
145   
146  0 XWikiContext xcontext = this.xcontextProvider.get();
147  0 try {
148  0 XWikiDocument template = xcontext.getWiki().getDocument(templateReference, xcontext);
149  0 String templateSyntax = template.getSyntax().toIdString();
150  0 String output = xcontext.getDoc().getRenderedContent(template.getContent(), templateSyntax, xcontext);
151    // Make sure the skin extension hooks are properly replaced with style sheets includes.
152  0 return xcontext.getWiki().getPluginManager().endParsing(output, xcontext);
153    } catch (XWikiException e) {
154  0 this.logger.debug("Failed to render [{}].", templateReference, e);
155  0 return null;
156    }
157    }
158   
 
159  22 toggle @Override
160    public String toAnnotatedXHTML(String source, String syntaxId)
161    {
162  22 XWikiDocument originalSecurityDocument = setSecurityDocument(createSecurityDocument());
163   
164    // Save the value of the "is in rendering engine" context property.
165  22 Object isInRenderingEngine = this.xcontextProvider.get().get(IS_IN_RENDERING_ENGINE);
166   
167  22 try {
168    // This tells display() methods that we are inside the rendering engine and thus that they can return wiki
169    // syntax and not HTML syntax (which is needed when outside the rendering engine, i.e. when we're inside
170    // templates using only Velocity for example).
171  22 this.xcontextProvider.get().put(IS_IN_RENDERING_ENGINE, true);
172   
173  22 return this.htmlConverter.toHTML(source, syntaxId);
174    } catch (Exception e) {
175    // Return the source text in case of an exception.
176  0 return source;
177    } finally {
178    // Restore the value of the value of the "is in rendering engine" context property.
179  22 if (isInRenderingEngine != null) {
180  0 this.xcontextProvider.get().put(IS_IN_RENDERING_ENGINE, isInRenderingEngine);
181    } else {
182  22 this.xcontextProvider.get().remove(IS_IN_RENDERING_ENGINE);
183    }
184   
185  22 setSecurityDocument(originalSecurityDocument);
186    }
187    }
188   
 
189  326 toggle @Override
190    public WysiwygEditorConfiguration getConfig()
191    {
192  326 return this.editorConfiguration;
193    }
194   
195    /**
196    * When the user switches to the Source tab he'll be able to make modifications and when he switches back to the
197    * WYSIWYG tab his changes will be rendered. If the document had PR, then we need to be sure that if the user
198    * doesn't have PR he won't be able to execute the code. We do this by setting as security document a clone of the
199    * current document that has the current user as content author (because the content author is used to check PR).
200    */
 
201  22 toggle private XWikiDocument createSecurityDocument()
202    {
203  22 XWikiContext xwikiContext = this.xcontextProvider.get();
204    // We clone the document in order to not impact the environment (the document cache for example).
205  22 XWikiDocument clonedDocument = xwikiContext.getDoc().clone();
206  22 clonedDocument.setContentAuthorReference(xwikiContext.getUserReference());
207  22 return clonedDocument;
208    }
209   
210    /**
211    * Sets the document that is going to be used to check for programming rights.
212    *
213    * @param document the document that is going to be used to check for programming rights
214    * @return the previous security document
215    */
 
216  44 toggle private XWikiDocument setSecurityDocument(XWikiDocument document)
217    {
218  44 return (XWikiDocument) this.xcontextProvider.get().put(XWikiDocument.CKEY_SDOC, document);
219    }
220    }