@Override public String serialize(ResourceReference reference) { StringBuilder buffer = new StringBuilder(); if (reference.getReference() != null) { // Make sure we escape special chars: # and ? as they have special meaning in links, but only // for // links to documents. Also escape \ since it's the escape char. String normalizedReference = addEscapesToReferencePart(reference.getReference()); buffer.append(normalizedReference); // Since we don`t have typed references in the 2.0 syntax, we need to reuse the untyped // document reference // syntax and make it explicit that it's about the WebHome document of the space. // This is most useful when converting from 2.1 back to 2.0. buffer.append(".WebHome"); } String anchor = reference.getParameter(DocumentResourceReference.ANCHOR); if (anchor != null) { buffer.append('#'); buffer.append(addEscapesToExtraParts(anchor)); } String queryString = reference.getParameter(DocumentResourceReference.QUERY_STRING); if (queryString != null) { buffer.append('?'); buffer.append(addEscapesToExtraParts(queryString)); } return buffer.toString(); }
private XHTMLLinkTypeRenderer getXHTMLLinkTypeRenderer(ResourceReference reference) { XHTMLLinkTypeRenderer renderer; // TODO: This is probably not very performant since it's called at each begin/endLink. try { renderer = this.componentManagerProvider .get() .getInstance(XHTMLLinkTypeRenderer.class, reference.getType().getScheme()); } catch (ComponentLookupException e) { // There's no specific XHTML Link Type Renderer for the passed link type, use the default // renderer. renderer = this.defaultLinkTypeRenderer; } renderer.setHasLabel(this.hasLabel); renderer.setXHTMLWikiPrinter(getXHTMLWikiPrinter()); return renderer; }
private void updateRelativeLinks(XWikiDocument document, DocumentReference oldDocumentReference) throws XWikiException { // We support only the syntaxes for which there is an available renderer. if (!this.contextComponentManagerProvider .get() .hasComponent(BlockRenderer.class, document.getSyntax().toIdString())) { this.logger.warn( "We can't update the relative links from [{}]" + " because there is no renderer available for its syntax [{}].", document.getDocumentReference(), document.getSyntax()); return; } DocumentReference newDocumentReference = document.getDocumentReference(); XDOM xdom = document.getXDOM(); List<Block> blocks = linkedResourceHelper.getBlocks(xdom); boolean modified = false; for (Block block : blocks) { ResourceReference resourceReference = linkedResourceHelper.getResourceReference(block); if (resourceReference == null) { // Skip invalid blocks. continue; } ResourceType resourceType = resourceReference.getType(); // TODO: support ATTACHMENT as well. if (!ResourceType.DOCUMENT.equals(resourceType) && !ResourceType.SPACE.equals(resourceType)) { // We are currently only interested in Document or Space references. continue; } // current link, use the old document's reference to fill in blanks. EntityReference oldLinkReference = this.resourceReferenceResolver.resolve(resourceReference, null, oldDocumentReference); // new link, use the new document's reference to fill in blanks. EntityReference newLinkReference = this.resourceReferenceResolver.resolve(resourceReference, null, newDocumentReference); // If the new and old link references don`t match, then we must update the relative link. if (!newLinkReference.equals(oldLinkReference)) { modified = true; // Serialize the old (original) link relative to the new document's location, in compact // form. String serializedLinkReference = this.compactEntityReferenceSerializer.serialize(oldLinkReference, newDocumentReference); // Update the reference in the XDOM. linkedResourceHelper.setResourceReferenceString(block, serializedLinkReference); } } if (modified) { document.setContent(xdom); saveDocumentPreservingContentAuthor(document, "Updated the relative links.", true); this.logger.info("Updated the relative links from [{}].", document.getDocumentReference()); } else { this.logger.info("No relative links to update in [{}].", document.getDocumentReference()); } }
private boolean renameLink( Block block, DocumentReference currentDocumentReference, DocumentReference oldTarget, DocumentReference newTarget) throws InvalidArgumentException { boolean modified = false; ResourceReference resourceReference = linkedResourceHelper.getResourceReference(block); if (resourceReference == null) { // Skip invalid blocks. throw new InvalidArgumentException(); } ResourceType resourceType = resourceReference.getType(); // TODO: support ATTACHMENT as well. if (!ResourceType.DOCUMENT.equals(resourceType) && !ResourceType.SPACE.equals(resourceType)) { // We are currently only interested in Document or Space references. throw new InvalidArgumentException(); } // Resolve the resource reference. EntityReference linkEntityReference = resourceReferenceResolver.resolve(resourceReference, null, currentDocumentReference); // Resolve the document of the reference. DocumentReference linkTargetDocumentReference = defaultReferenceDocumentReferenceResolver.resolve(linkEntityReference); EntityReference newTargetReference = newTarget; ResourceType newResourceType = resourceType; // If the link was resolved to a space... if (EntityType.SPACE.equals(linkEntityReference.getType())) { if (XWiki.DEFAULT_SPACE_HOMEPAGE.equals(newTarget.getName())) { // If the new document reference is also a space (non-terminal doc), be careful to keep it // serialized as a space still (i.e. without ".WebHome") and not serialize it as a doc by // mistake // (i.e. with ".WebHome"). newTargetReference = newTarget.getLastSpaceReference(); } else { // If the new target is a non-terminal document, we can not use a "space:" resource type to // access // it anymore. To fix it, we need to change the resource type of the link reference "doc:". newResourceType = ResourceType.DOCUMENT; } } // If the link targets the old (renamed) document reference, we must update it. if (linkTargetDocumentReference.equals(oldTarget)) { modified = true; String newReferenceString = this.compactEntityReferenceSerializer.serialize( newTargetReference, currentDocumentReference); // Update the reference in the XDOM. linkedResourceHelper.setResourceReferenceString(block, newReferenceString); linkedResourceHelper.setResourceType(block, newResourceType); } return modified; }
@Test public void testParseWhenInWikiMode() throws Exception { // Create a Mock WikiModel implementation so that the link parser works in wiki mode this.componentManager.registerMockComponent(WikiModel.class); ResourceReference reference = parser.parse(""); Assert.assertEquals("", reference.getReference()); Assert.assertFalse(reference.isTyped()); Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); Assert.assertEquals("Typed = [false] Type = [doc] Reference = []", reference.toString()); reference = parser.parse("Hello World"); Assert.assertEquals("Hello World", reference.getReference()); Assert.assertFalse(reference.isTyped()); Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); Assert.assertEquals( "Typed = [false] Type = [doc] Reference = [Hello World]", reference.toString()); reference = parser.parse("http://xwiki.org"); Assert.assertEquals("http://xwiki.org", reference.getReference()); Assert.assertFalse(reference.isTyped()); Assert.assertEquals(ResourceType.URL, reference.getType()); Assert.assertEquals( "Typed = [false] Type = [url] Reference = [http://xwiki.org]", reference.toString()); // Verify mailto: URI is recognized reference = parser.parse("mailto:[email protected]?subject=test"); Assert.assertEquals("[email protected]?subject=test", reference.getReference()); Assert.assertTrue(reference.isTyped()); Assert.assertEquals(ResourceType.MAILTO, reference.getType()); Assert.assertEquals( "Typed = [true] Type = [mailto] Reference = [[email protected]?subject=test]", reference.toString()); // Verify attach: URI is recognized reference = parser.parse("attach:some:content"); Assert.assertEquals("some:content", reference.getReference()); Assert.assertTrue(reference.isTyped()); Assert.assertEquals(ResourceType.ATTACHMENT, reference.getType()); Assert.assertEquals( "Typed = [true] Type = [attach] Reference = [some:content]", reference.toString()); // Verify that unknown URIs are ignored // Note: In this example we point to a document and we consider that myxwiki is the wiki name // and // http://xwiki.org is the page name reference = parser.parse("mywiki:http://xwiki.org"); Assert.assertEquals("mywiki:http://xwiki.org", reference.getReference()); Assert.assertFalse(reference.isTyped()); Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); Assert.assertEquals( "Typed = [false] Type = [doc] Reference = [mywiki:http://xwiki.org]", reference.toString()); // Verify doc links work reference = parser.parse("doc:wiki:space.page"); Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); Assert.assertEquals("wiki:space.page", reference.getReference()); Assert.assertEquals( "Typed = [true] Type = [doc] Reference = [wiki:space.page]", reference.toString()); Assert.assertTrue(reference.isTyped()); // Verify InterWiki links work reference = parser.parse("interwiki:alias:content"); Assert.assertEquals(ResourceType.INTERWIKI, reference.getType()); Assert.assertEquals("content", reference.getReference()); Assert.assertTrue(reference.isTyped()); Assert.assertEquals("alias", ((InterWikiResourceReference) reference).getInterWikiAlias()); Assert.assertEquals( "Typed = [true] Type = [interwiki] Reference = [content] " + "Parameters = [[interWikiAlias] = [alias]]", reference.toString()); // Verify that an invalid InterWiki link is considered as Document link reference = parser.parse("interwiki:invalid_since_doesnt_have_colon"); Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); Assert.assertEquals("interwiki:invalid_since_doesnt_have_colon", reference.getReference()); Assert.assertFalse(reference.isTyped()); Assert.assertEquals( "Typed = [false] Type = [doc] Reference = [interwiki:invalid_since_doesnt_have_colon]", reference.toString()); // Verify typed URLs reference = parser.parse("url:http://xwiki.org"); Assert.assertEquals(ResourceType.URL, reference.getType()); Assert.assertTrue(reference.isTyped()); Assert.assertEquals("http://xwiki.org", reference.getReference()); Assert.assertEquals( "Typed = [true] Type = [url] Reference = [http://xwiki.org]", reference.toString()); // Verify query string and anchors have no meaning in link reference to documents. reference = parser.parse("Hello World?no=queryString#notAnAnchor"); Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); Assert.assertEquals("Hello World?no=queryString#notAnAnchor", reference.getReference()); Assert.assertFalse(reference.isTyped()); Assert.assertNull(((DocumentResourceReference) reference).getAnchor()); Assert.assertNull(((DocumentResourceReference) reference).getQueryString()); Assert.assertEquals( "Typed = [false] Type = [doc] Reference = [Hello World?no=queryString#notAnAnchor]", reference.toString()); // Verify that the interwiki separator from XWiki Syntax 2.0 has not meaning in link references // to documents reference = parser.parse("page@alias"); Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); Assert.assertFalse(reference.isTyped()); Assert.assertEquals("page@alias", reference.getReference()); Assert.assertEquals( "Typed = [false] Type = [doc] Reference = [page@alias]", reference.toString()); // Verify path link types reference = parser.parse("path:/some/path"); Assert.assertEquals(ResourceType.PATH, reference.getType()); Assert.assertTrue(reference.isTyped()); Assert.assertEquals("/some/path", reference.getReference()); Assert.assertEquals( "Typed = [true] Type = [path] Reference = [/some/path]", reference.toString()); // Verify UNC link types reference = parser.parse("unc:\\\\myserver\\myshare\\mydoc.txt"); Assert.assertEquals(ResourceType.UNC, reference.getType()); Assert.assertTrue(reference.isTyped()); Assert.assertEquals("\\\\myserver\\myshare\\mydoc.txt", reference.getReference()); Assert.assertEquals( "Typed = [true] Type = [unc] Reference = [\\\\myserver\\myshare\\mydoc.txt]", reference.toString()); // Verify that reference escapes are left as is by the link parser reference = this.parser.parse("pa\\.ge"); Assert.assertEquals(ResourceType.DOCUMENT, reference.getType()); Assert.assertEquals("pa\\.ge", reference.getReference()); }
@Test public void testParseWhenNotInWikiMode() throws Exception { // Verify that mailto: links are treated normally even when in non wiki mode ResourceReference reference = parser.parse("mailto:something"); Assert.assertEquals("something", reference.getReference()); Assert.assertTrue(reference.isTyped()); Assert.assertEquals(ResourceType.MAILTO, reference.getType()); Assert.assertEquals( "Typed = [true] Type = [mailto] Reference = [something]", reference.toString()); // Verify that non typed links are treated as URLs reference = parser.parse("something"); Assert.assertEquals("something", reference.getReference()); Assert.assertFalse(reference.isTyped()); Assert.assertEquals(ResourceType.URL, reference.getType()); Assert.assertEquals( "Typed = [false] Type = [url] Reference = [something]", reference.toString()); // Verify that doc: links are treated as URLs reference = parser.parse("doc:something"); Assert.assertEquals("doc:something", reference.getReference()); Assert.assertFalse(reference.isTyped()); Assert.assertEquals(ResourceType.URL, reference.getType()); Assert.assertEquals( "Typed = [false] Type = [url] Reference = [doc:something]", reference.toString()); // Verify that attach: links are treated as URLs reference = parser.parse("attach:something"); Assert.assertEquals("attach:something", reference.getReference()); Assert.assertFalse(reference.isTyped()); Assert.assertEquals(ResourceType.URL, reference.getType()); Assert.assertEquals( "Typed = [false] Type = [url] Reference = [attach:something]", reference.toString()); }
@Override public void filter(Document htmlDocument, Map<String, String> cleaningParams) { String targetDocument = cleaningParams.get("targetDocument"); DocumentReference targetDocumentReference = null; List<Element> images = filterDescendants(htmlDocument.getDocumentElement(), new String[] {TAG_IMG}); for (Element image : images) { if (targetDocumentReference == null && !StringUtils.isBlank(targetDocument)) { targetDocumentReference = this.documentStringReferenceResolver.resolve(targetDocument); } String src = image.getAttribute(ATTRIBUTE_SRC); // If it's a Data URI scheme don't touch it if (!src.startsWith("data:")) { if (!StringUtils.isBlank(src) && targetDocumentReference != null) { // OpenOffice 3.2 server generates relative image paths, extract image name. int separator = src.lastIndexOf("/"); if (-1 != separator) { src = src.substring(separator + 1); } try { // We have to decode the image file name in case it contains URL special characters. src = URLDecoder.decode(src, "UTF-8"); } catch (UnsupportedEncodingException e) { // This should never happen. } // Set image source attribute relative to the reference document. AttachmentReference attachmentReference = new AttachmentReference(src, targetDocumentReference); image.setAttribute( ATTRIBUTE_SRC, this.documentAccessBridge.getAttachmentURL(attachmentReference, false)); // The 'align' attribute of images creates a lot of problems. First,the office server has // a problem // with // center aligning images (it aligns them to left). Next, the office server uses <br // clear"xxx"> for // avoiding content wrapping around images which is not valid XHTML. There for, to be // consistent and // simple we will remove the 'align' attribute of all the images so that they are all left // aligned. image.removeAttribute(ATTRIBUTE_ALIGN); } else if (src.startsWith("file://")) { src = "Missing.png"; image.setAttribute(ATTRIBUTE_SRC, src); image.setAttribute(ATTRIBUTE_ALT, src); } ResourceReference imageReference = new ResourceReference(src, ResourceType.ATTACHMENT); imageReference.setTyped(false); Comment beforeComment = htmlDocument.createComment( XMLUtils.escapeXMLComment( "startimage:" + this.xhtmlMarkerSerializer.serialize(imageReference))); Comment afterComment = htmlDocument.createComment("stopimage"); image.getParentNode().insertBefore(beforeComment, image); image.getParentNode().insertBefore(afterComment, image.getNextSibling()); } } }