1 /*******************************************************************************
2  * Copyright (c) 2000, 2020 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     George Suaridze <suag@1c.ru> (1C-Soft LLC) - Bug 560168
14  *******************************************************************************/
15 package org.eclipse.help.internal.webapp.data;
16 
17 import java.util.ArrayList;
18 import java.util.List;
19 import java.util.regex.Matcher;
20 import java.util.regex.Pattern;
21 
22 import javax.servlet.ServletContext;
23 import javax.servlet.http.HttpServletRequest;
24 import javax.servlet.http.HttpServletResponse;
25 
26 import org.eclipse.core.runtime.CoreException;
27 import org.eclipse.core.runtime.IConfigurationElement;
28 import org.eclipse.core.runtime.IExtensionRegistry;
29 import org.eclipse.core.runtime.Platform;
30 import org.eclipse.help.webapp.AbstractButton;
31 
32 /**
33  * Control for a toolbar.
34  */
35 public class ToolbarData extends RequestData {
36 
37 	private static final String BUTTON_EXTENSION_POINT = "org.eclipse.help.webapp.toolbarButton"; //$NON-NLS-1$
38 	private ToolbarButton[] buttons;
39 	private String[] scriptFiles;
40 	private static Pattern jsNamePattern = Pattern.compile("^[a-zA-Z_$][a-zA-Z1-9_]*"); //$NON-NLS-1$
41 
42 
ToolbarData(ServletContext context, HttpServletRequest request, HttpServletResponse response)43 	public ToolbarData(ServletContext context, HttpServletRequest request,
44 			HttpServletResponse response) {
45 		super(context, request, response);
46 		loadButtons();
47 	}
48 
49 	/*
50 	 * Returns whether or not this toolbar has a menu button (has an arrow with drop
51 	 * down menu).
52 	 */
hasMenu()53 	public boolean hasMenu() {
54 		for (ToolbarButton button : buttons) {
55 			if ("menu".equals(button.getAction())) { //$NON-NLS-1$
56 				return true;
57 			}
58 		}
59 		return false;
60 	}
61 
loadButtons()62 	private void loadButtons() {
63 		String[] names = request.getParameterValues("name"); //$NON-NLS-1$
64 		String[] tooltips = request.getParameterValues("tooltip"); //$NON-NLS-1$
65 		String[] images = request.getParameterValues("image"); //$NON-NLS-1$
66 		String[] actions = request.getParameterValues("action"); //$NON-NLS-1$
67 		String[] params = request.getParameterValues("param"); //$NON-NLS-1$
68 		String[] states = request.getParameterValues("state"); //$NON-NLS-1$
69 
70 		if (names == null || tooltips == null || images == null
71 				|| actions == null || params == null || states == null
72 				|| names.length != tooltips.length
73 				|| names.length != images.length
74 				|| names.length != actions.length
75 				|| names.length != params.length
76 				|| names.length != states.length) {
77 			buttons = new ToolbarButton[0];
78 			scriptFiles = new String[0];
79 			return;
80 		}
81 
82 		List<ToolbarButton> buttonList = new ArrayList<>();
83 		for (int i = 0; i < names.length; i++) {
84 			if ("".equals(names[i])) //$NON-NLS-1$
85 				buttonList.add(new ToolbarButton());
86 			else{
87 				// Is this a valid javascript name (and not a script injection)
88 				Matcher matcher = jsNamePattern.matcher(names[i]);
89 				if (matcher.matches())
90 					buttonList.add(new ToolbarButton(names[i], ServletResources
91 							.getString(tooltips[i], request), preferences
92 							.getImagesDirectory()
93 							+ "/e_" + images[i], //$NON-NLS-1$
94 							actions[i], params[i], states[i]));
95 			}
96 		}
97 
98 		addExtensionButtons(buttonList);
99 
100 		// add implicit maximize/restore button on all toolbars
101 		if (isIE() || isMozilla()
102 				&& "1.2.1".compareTo(getMozillaVersion()) <= 0 //$NON-NLS-1$
103 				|| (isSafari() && "120".compareTo(getSafariVersion()) <= 0)) { //$NON-NLS-1$
104 			buttonList.add(new ToolbarButton("maximize_restore", //$NON-NLS-1$
105 					getMaximizeTooltip(), preferences.getImagesDirectory()
106 							+ "/" + "maximize.svg", //$NON-NLS-1$ //$NON-NLS-2$
107 					"restore_maximize", null, "off")); //$NON-NLS-1$ //$NON-NLS-2$
108 		}
109 		buttons = buttonList
110 				.toArray(new ToolbarButton[buttonList.size()]);
111 	}
112 
addExtensionButtons(List<ToolbarButton> buttonList)113 	private void addExtensionButtons(List<ToolbarButton> buttonList) {
114 		IExtensionRegistry registry = Platform.getExtensionRegistry();
115 		IConfigurationElement[] elements = registry
116 				.getConfigurationElementsFor(BUTTON_EXTENSION_POINT);
117 
118 		List<AbstractButton> extensionButtons = new ArrayList<>();
119 		List<String> scripts = new ArrayList<>();
120 		for (IConfigurationElement element : elements) {
121 			Object obj = null;
122 			try {
123 				obj = element.createExecutableExtension("class"); //$NON-NLS-1$
124 			} catch (CoreException e) {
125 				Platform.getLog(getClass()).error("Create extension failed:[" //$NON-NLS-1$
126 						+ BUTTON_EXTENSION_POINT + "].", e); //$NON-NLS-1$
127 			}
128 			if (obj instanceof AbstractButton) {
129 				AbstractButton button = (AbstractButton) obj;
130 				String toolbarName = request.getParameter("view"); //$NON-NLS-1$
131 				if (toolbarName == null)
132 				{
133 					toolbarName = request.getParameter("toolbar"); //$NON-NLS-1$
134 				}
135 				if (button.isAddedToToolbar(toolbarName)) {
136 					extensionButtons.add(button);
137 				}
138 			}
139 		}
140 
141 		extensionButtons.sort(null);
142 
143 		for (AbstractButton button : extensionButtons) {
144 			String scriptFile = button.getJavaScriptURL();
145 			if (scriptFile != null) {
146 				scripts.add(UrlUtil.getRelativePath(request, scriptFile));
147 			}
148 			ToolbarButton toolButton = new ToolbarButton(button.getId(),
149 					button.getTooltip(UrlUtil.getLocaleObj(request, response)),
150 					request.getContextPath() + button.getImageURL(),
151 					button.getAction(),
152 					"", //$NON-NLS-1$
153 					button.getState());
154 			 buttonList.add(toolButton);
155 		}
156 		scriptFiles = scripts.toArray(new String[scripts.size()]);
157 	}
158 
getButtons()159 	public ToolbarButton[] getButtons() {
160 		return buttons;
161 	}
162 
getName()163 	public String getName() {
164 		if (request.getParameter("view") == null) //$NON-NLS-1$
165 			return ""; //$NON-NLS-1$
166 		return request.getParameter("view"); //$NON-NLS-1$
167 	}
168 
getTitle()169 	public String getTitle() {
170 		if (request.getParameter("view") == null) //$NON-NLS-1$
171 			return ""; //$NON-NLS-1$
172 		return ServletResources.getString(request.getParameter("view"), //$NON-NLS-1$
173 					request);
174 	}
175 
getScript()176 	public String getScript() {
177 		return request.getParameter("script"); //$NON-NLS-1$
178 	}
getMaximizeImage()179 	public String getMaximizeImage() {
180 		return preferences.getImagesDirectory() + "/e_maximize.svg"; //$NON-NLS-1$
181 	}
getRestoreImage()182 	public String getRestoreImage() {
183 		return preferences.getImagesDirectory() + "/e_restore.svg"; //$NON-NLS-1$
184 	}
getMaximizeTooltip()185 	public String getMaximizeTooltip() {
186 		return ServletResources.getString("maximize", request); //$NON-NLS-1$
187 	}
getRestoreTooltip()188 	public String getRestoreTooltip() {
189 		return ServletResources.getString("restore", request); //$NON-NLS-1$
190 	}
191 
getScriptFiles()192 	public String[] getScriptFiles() {
193 		return scriptFiles;
194 	}
195 }
196