/* * ConcourseConnect * Copyright 2009 Concursive Corporation * http://www.concursive.com * * This file is part of ConcourseConnect, an open source social business * software and community platform. * * Concursive ConcourseConnect is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, version 3 of the License. * * Under the terms of the GNU Affero General Public License you must release the * complete source code for any application that uses any part of ConcourseConnect * (system header files and libraries used by the operating system are excluded). * These terms must be included in any work that has ConcourseConnect components. * If you are developing and distributing open source applications under the * GNU Affero General Public License, then you are free to use ConcourseConnect * under the GNU Affero General Public License. * * If you are deploying a web site in which users interact with any portion of * ConcourseConnect over a network, the complete source code changes must be made * available. For example, include a link to the source archive directly from * your web site. * * For OEMs, ISVs, SIs and VARs who distribute ConcourseConnect with their * products, and do not license and distribute their source code under the GNU * Affero General Public License, Concursive provides a flexible commercial * license. * * To anyone in doubt, we recommend the commercial license. Our commercial license * is competitively priced and will eliminate any confusion about how * ConcourseConnect can be used and distributed. * * ConcourseConnect is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with ConcourseConnect. If not, see <http://www.gnu.org/licenses/>. * * Attribution Notice: ConcourseConnect is an Original Work of software created * by Concursive Corporation */ package com.concursive.connect.web.modules.wiki.utils; import com.concursive.commons.text.StringUtils; import com.concursive.connect.web.modules.documents.dao.ImageInfo; import com.concursive.connect.web.modules.profile.dao.Project; import com.concursive.connect.web.modules.profile.utils.ProjectUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import java.net.URL; import java.util.HashMap; /** * Processes the wiki link as an image * * @author matt rajkowski * @created April 8, 2008 */ public class WikiImageLink { private static Log LOG = LogFactory.getLog(WikiImageLink.class); public static String CRLF = System.getProperty("line.separator"); private String value = ""; private boolean needsCRLF = true; public WikiImageLink(String link, int projectId, HashMap<String, ImageInfo> imageList, boolean lineTest, boolean editMode, String contextPath) { Project project = ProjectUtils.loadProject(projectId); StringBuffer sb = new StringBuffer(); String image = link.substring(6); String title = null; int frame = -1; int thumbnail = -1; int left = -1; int right = -1; int center = -1; int none = -1; int imageLink = -1; int alt = -1; if (image.indexOf("|") > 0) { // the image is first image = image.substring(0, image.indexOf("|")); // any directives are next frame = link.indexOf("|frame"); thumbnail = link.indexOf("|thumb"); left = link.indexOf("|left"); right = link.indexOf("|right"); center = link.indexOf("|center"); none = link.indexOf("|none"); imageLink = link.indexOf("|link="); alt = link.indexOf("|alt="); // the optional caption is last int last = link.lastIndexOf("|"); if (last > frame && last > thumbnail && last > left && last > right && last > center && last > none && last > imageLink && last > alt) { title = link.substring(last + 1); } } // Determine if local or external image String imageUrl = null; String panelImageUrl = null; if (!image.contains(".do?command=Img") && !image.contains("/wiki-image/") && (image.startsWith("http://") || image.startsWith("https://"))) { // external image try { URL url = new URL(image); imageUrl = image; } catch (Exception e) { LOG.error("Could not create URL based on input", e); } } else { // local image image = StringUtils.replace(image, "\\{", "["); image = StringUtils.replace(image, "\\}", "]"); imageUrl = contextPath + "/show/" + project.getUniqueId() + "/wiki-image/" + StringUtils.replace(StringUtils.jsEscape(image) + (thumbnail > -1 ? "?th=true" : ""), "%20", "+"); panelImageUrl = contextPath + "/show/" + project.getUniqueId() + "/wiki-image/" + StringUtils.replace(StringUtils.jsEscape(image), "%20", "+") + "?panel=true"; } if (imageUrl != null) { //A picture, including alternate text: // [[Image:Wiki.png|The logo for this Wiki]] //You can put the image in a frame with a caption: //[[Image:Wiki.png|frame|The logo for this Wiki]] // Access some image details int width = 0; int height = 0; int fullWidth = 0; ImageInfo imageInfo = imageList.get(image); if (imageInfo == null) { LOG.warn("Image not found: " + image); } else { if (thumbnail > -1) { // Use the typical thumbnail dimensions width = 210; height = 150; fullWidth = imageInfo.getWidth(); } else { // Determine the width and height for the output from the image width = imageInfo.getWidth(); height = imageInfo.getHeight(); fullWidth = width; } // Determine the version so that an image isn't cached with a prior version if (imageInfo.getVersion() > 1.0) { imageUrl += (!imageUrl.contains("?") ? "?" : "&") + "v=" + imageInfo.getVersion(); } } if (!editMode) { if (frame > -1 || thumbnail > -1) { // Width = the image width + border size * 2 + margin * 2 of inner div // Output the frame sb.append( "<div style=\"background: white; " + (width > 0 ? "max-width: " + width + "px; " : "") + (right > -1 ? "float: right; margin-left: 8px; margin-bottom: 4px; padding: 3px; text-align: center; " : "") + (left > -1 ? "float: left; margin-right: 8px; margin-bottom: 4px; padding: 3px; text-align: center; " : "") + (center > -1 ? "display: block; margin: 0 auto; " : "") + "position:relative; border: 1px solid #999999; margin-bottom: 5px; padding:5px; \">"); } } // Alt String altText = null; if (alt > -1) { int startIndex = alt + 4; int endIndex = link.indexOf("|", startIndex); if (endIndex == -1) { endIndex = link.length(); } altText = link.substring(startIndex, endIndex); } // Looks like the image needs a link (which is always last) if (imageLink > -1) { // Get the entered link int startIndex = imageLink + 6; int endIndex = link.length(); String href = link.substring(startIndex, endIndex); // Treat as a wikiLink to validate and to create a proper url LOG.debug("Create a wiki link from: " + href); WikiLink wikiLink = new WikiLink(project.getId(), (altText != null ? href + " " + altText : href)); String url = wikiLink.getUrl(contextPath); sb.append("<a href=\""); sb.append(url); sb.append("\""); if (!editMode && "app".equals(wikiLink.getArea())) { // open apps in a panel sb.append(" rel=\"shadowbox\""); } // If an external link, open in a new window if (wikiLink.getStatus().equals(WikiLink.REFERENCE)) { if (url.startsWith("http://") || url.startsWith("https://")) { sb.append(" target=\"_blank\""); } } // Show alt text if (StringUtils.hasText(wikiLink.getName())) { sb.append(" alt=\"").append(StringUtils.toHtmlValue(wikiLink.getName())).append("\""); } sb.append(">"); } // Output the image sb.append( "<img " + (width > 0 ? "width=\"" + width + "\" " : "") + (height > 0 ? "height=\"" + height + "\" " : "") + (right > -1 && ((frame == -1 && thumbnail == -1) || editMode) ? "style=\"float: right; margin-left: 8px; margin-bottom: 4px;\" " : "") + (left > -1 && ((frame == -1 && thumbnail == -1) || editMode) ? "style=\"float: left; margin-right: 8px; margin-bottom: 4px;\" " : "") + (center > -1 ? "style=\"display: block; margin: 0 auto;\" " : "") + "src=\"" + imageUrl + "\" " + (StringUtils.hasText(title) ? "title=\"" + StringUtils.toHtmlValue(title) + "\"" : "") + " " + "alt=\"" + StringUtils.toHtmlValue(image) + "\" />"); // Close the image link if (imageLink > -1) { sb.append("</a>"); } if (!editMode) { if (frame > -1 || thumbnail > -1) { sb.append("<div id=\"caption\" style=\"text-align: left;\">"); } if (thumbnail > -1) { sb.append( "<div style=\"float:right\">" + "<a " + "href=\"" + panelImageUrl + "\" " + "rel=\"shadowbox[wikiImages];width=660;imageWidth=640;imageHeight=480;imageUrl=" + panelImageUrl + "\" " + "title=\"" +(StringUtils.hasText(title) ? StringUtils.toHtmlValue(title) : " ") + "\">" + "<img src=\"" + contextPath + "/images/magnify-clip.png\" width=\"15\" height=\"11\" alt=\"Enlarge\" border=\"0\" />" + "</a>" + "</div>"); } if (frame > -1 || thumbnail > -1) { if (title != null) { sb.append(StringUtils.toHtml(title)); } else { sb.append(" "); } sb.append("</div></div>"); } // Close the frame if (none > -1) { sb.append("<br clear=\"all\">"); } } if (lineTest && (right > -1 || left > -1) || none > -1) { needsCRLF = false; } value = sb.toString(); } } public String getValue() { return value; } public void setValue(String value) { this.value = value; } public boolean getNeedsCRLF() { return needsCRLF; } public void setNeedsCRLF(boolean needsCRLF) { this.needsCRLF = needsCRLF; } }