Generate HTML relative (to each peer) links from hosted WikiCode.

When WikiCode inserted in a peer hosted Blog, Wiki, Messages or Profile
contains relative links (images or any content, hosted in DATA/HTDOCS),
it is more reliable to keep these links relative, especially when the
peer is behind any kind of reverse Proxy.
This commit is contained in:
luccioman 2016-11-04 11:21:20 +01:00
parent 3444d947ac
commit 54d879a9b3
11 changed files with 80 additions and 58 deletions

View File

@ -44,6 +44,7 @@ import net.yacy.cora.protocol.HeaderFramework;
import net.yacy.cora.protocol.RequestHeader;
import net.yacy.data.BlogBoard;
import net.yacy.data.UserDB;
import net.yacy.http.servlets.YaCyDefaultServlet;
import net.yacy.peers.NewsPool;
import net.yacy.peers.Seed;
import net.yacy.search.Switchboard;
@ -78,14 +79,15 @@ public class Blog {
final boolean xml = (header.get(HeaderFramework.CONNECTION_PROP_PATH)).endsWith(".xml");
final String address = sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP());
/* Peer URL base : used to generate absolute URLs in Blog.rss */
final String context = YaCyDefaultServlet.getContext(header, sb);
prop.put("mode_admin", hasRights ? "1" : "0");
if (post == null) {
prop.putHTML("peername", sb.peers.mySeed().getName());
prop.put("address", address);
return putBlogDefault(prop, sb, address, 0, 10, hasRights, xml);
prop.put("context", context);
return putBlogDefault(prop, sb, context, 0, 10, hasRights, xml);
}
final int start = post.getInt("start",0); //indicates from where entries should be shown
@ -192,7 +194,7 @@ public class Blog {
prop.putHTML("mode_author", UTF8.String(author));
prop.putHTML("mode_subject", post.get("subject",""));
prop.put("mode_date", dateString(new Date()));
prop.putWiki(sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP()), "mode_page", post.get("content", ""));
prop.putWiki("mode_page", post.get("content", ""));
prop.putHTML("mode_page-code", post.get("content", ""));
}
else {
@ -228,14 +230,14 @@ public class Blog {
// XXX: where are "peername" and "address" used in the template?
// XXX: "clientname" is already set to the peername, no need for a new setting
prop.putHTML("peername", sb.peers.mySeed().getName());
prop.put("address", address);
prop.put("context", context);
//index all entries
putBlogDefault(prop, sb, address, start, num, hasRights, xml);
putBlogDefault(prop, sb, context, start, num, hasRights, xml);
}
else {
//only show 1 entry
prop.put("mode_entries", "1");
putBlogEntry(sb, prop, page, address, 0, hasRights, xml);
putBlogEntry(prop, page, context, 0, hasRights, xml);
}
}
@ -246,7 +248,7 @@ public class Blog {
private static serverObjects putBlogDefault(
final serverObjects prop,
final Switchboard switchboard,
final String address,
final String context,
int start,
int num,
final boolean hasRights,
@ -264,10 +266,9 @@ public class Blog {
while (i.hasNext() && (num == 0 || num > count)) {
if(0 < start--) continue;
putBlogEntry(
switchboard,
prop,
switchboard.blogDB.readBlogEntry(i.next()),
address,
context,
count++,
hasRights,
xml);
@ -295,10 +296,9 @@ public class Blog {
}
private static serverObjects putBlogEntry(
final Switchboard sb,
final serverObjects prop,
final BlogBoard.BlogEntry entry,
final String address,
final String context,
final int number,
final boolean hasRights,
final boolean xml)
@ -313,21 +313,21 @@ public class Blog {
} else {
prop.put("mode_entries_" + number + "_commentsactive", "1");
prop.put("mode_entries_" + number + "_commentsactive_pageid", entry.getKey());
prop.put("mode_entries_" + number + "_commentsactive_address", address);
prop.put("mode_entries_" + number + "_commentsactive_context", context);
prop.put("mode_entries_" + number + "_commentsactive_comments", entry.getCommentsSize());
}
prop.put("mode_entries_" + number + "_date", dateString(entry.getDate()));
prop.put("mode_entries_" + number + "_rfc822date", HeaderFramework.formatRFC1123(entry.getDate()));
prop.put("mode_entries_" + number + "_pageid", entry.getKey());
prop.put("mode_entries_" + number + "_address", address);
prop.put("mode_entries_" + number + "_context", context);
prop.put("mode_entries_" + number + "_ip", entry.getIp());
if (xml) {
prop.put("mode_entries_" + number + "_page", entry.getPage());
prop.put("mode_entries_" + number + "_timestamp", entry.getTimestamp());
} else {
prop.putWiki(sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP()), "mode_entries_" + number + "_page", entry.getPage());
prop.putWiki("mode_entries_" + number + "_page", entry.getPage());
}
if (hasRights) {

View File

@ -2,22 +2,22 @@
<rss version="2.0">
<channel>
<title><![CDATA[YaCy '#[clientname]#': Blog]]></title>
<link>http://#[address]#/Blog.html</link>
<link>#[context]#/Blog.html</link>
<image>
<url>http://#[address]#/env/grafics/YaCyLogo_60ppi.png</url>
<url>#[context]#/env/grafics/YaCyLogo_60ppi.png</url>
<title>YaCy</title>
<link>http://#[address]#/</link>
<link>#[context]#/</link>
</image>
#(mode)# #{entries}#<item>
<author><![CDATA[#[author]#]]></author>
<title><![CDATA[#[subject]#]]></title>
<link>http://#[address]#/Blog.html?page=#[pageid]#</link>
<link>#[context]#/Blog.html?page=#[pageid]#</link>
<pubDate>#[rfc822date]#</pubDate>
<guid>#[pageid]#</guid>
<description><![CDATA[
#[page]#]]></description>
#(commentsactive)#::<comments>http://#[address]#/BlogComments.html?page=#[pageid]#</comments>#(/commentsactive)#
#(commentsactive)#::<comments>#[context]#/BlogComments.html?page=#[pageid]#</comments>#(/commentsactive)#
</item>#{/entries}# #(/mode)#
</channel>
</rss>

View File

@ -176,7 +176,7 @@ public class BlogComments {
prop.putHTML("mode_allow_author", UTF8.String(author));
prop.putHTML("mode_subject", post.get("subject",""));
prop.put("mode_date", dateString(new Date()));
prop.putWiki(sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP()), "mode_page", post.get("content", ""));
prop.putWiki("mode_page", post.get("content", ""));
prop.put("mode_page-code", post.get("content", ""));
} else {
// show blog-entry/entries
@ -192,7 +192,7 @@ public class BlogComments {
prop.putHTML("mode_allow_author", UTF8.String(author));
prop.put("mode_comments", page.getCommentsSize());
prop.put("mode_date", dateString(page.getDate()));
prop.putWiki(sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP()), "mode_page", page.getPage());
prop.putWiki("mode_page", page.getPage());
if (hasRights) {
prop.put("mode_admin", "1");
prop.put("mode_admin_pageid", page.getKey());
@ -235,7 +235,7 @@ public class BlogComments {
if (!xml) {
prop.putHTML("mode_entries_"+count+"_subject", UTF8.String(entry.getSubject()));
prop.putHTML("mode_entries_"+count+"_author", UTF8.String(entry.getAuthor()));
prop.putWiki(sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP()), "mode_entries_"+count+"_page", entry.getPage());
prop.putWiki("mode_entries_"+count+"_page", entry.getPage());
} else {
prop.putHTML("mode_entries_"+count+"_subject", UTF8.String(entry.getSubject()));
prop.putHTML("mode_entries_"+count+"_author", UTF8.String(entry.getAuthor()));

View File

@ -118,7 +118,7 @@ public class MessageSend_p {
prop.putXML("mode_permission_message", message);
prop.putHTML("mode_permission_hash", hash);
if (post.containsKey("preview")) {
prop.putWiki(sb.peers.mySeed().getPublicAddress(ip), "mode_permission_previewmessage", message);
prop.putWiki("mode_permission_previewmessage", message);
}
} catch (final NumberFormatException e) {

View File

@ -36,6 +36,7 @@ import net.yacy.cora.document.encoding.UTF8;
import net.yacy.cora.protocol.HeaderFramework;
import net.yacy.cora.protocol.RequestHeader;
import net.yacy.data.MessageBoard;
import net.yacy.http.servlets.YaCyDefaultServlet;
import net.yacy.peers.Seed;
import net.yacy.search.Switchboard;
import net.yacy.search.SwitchboardConstants;
@ -58,10 +59,10 @@ public class Messages_p {
final Switchboard sb = (Switchboard) env;
final serverObjects prop = new serverObjects();
// set peer address / name
final String peerAddress = sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP());
/* Peer URL base : used by Messages_p.rss to render absolute URL links to this peer */
final String context = YaCyDefaultServlet.getContext(header, sb);
final String peerName = sb.peers.mySeed().getName();
prop.put("peerAddress", peerAddress);
prop.put("context", context);
prop.putXML("peerName", peerName);
// List known hosts for message sending (from Blacklist_p.java)
@ -132,7 +133,7 @@ public class Messages_p {
if ((header.get(HeaderFramework.CONNECTION_PROP_PATH)).endsWith(".rss")) {
// set the peer address
prop.put("mode_messages_"+count+"_peerAddress", peerAddress);
prop.put("mode_messages_"+count+"_context", context);
// set the rfc822 date
prop.put("mode_messages_"+count+"_rfc822Date", HeaderFramework.formatRFC1123(message.date()));
@ -162,7 +163,7 @@ public class Messages_p {
prop.putXML("mode_subject", message.subject());
String theMessage = null;
theMessage = UTF8.String(message.message());
prop.putWiki(sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP()), "mode_message", theMessage);
prop.putWiki("mode_message", theMessage);
prop.put("mode_hash", message.authorHash());
prop.putXML("mode_key", key);
}

View File

@ -2,11 +2,11 @@
<rss version="2.0">
<channel>
<title><![CDATA[YaCy '#[clientname]#': Messages]]></title>
<link>http://#[peerAddress]#/Messages_p.html</link>
<link>#[context]#/Messages_p.html</link>
<image>
<url>http://#[peerAddress]#/env/grafics/YaCyLogo_60ppi.png</url>
<url>#[context]#/env/grafics/YaCyLogo_60ppi.png</url>
<title>YaCy</title>
<link>http://#[peerAddress]#/</link>
<link>#[context]#/</link>
</image>
#(mode)#
#{messages}#
@ -14,7 +14,7 @@
<author><![CDATA[#[from]#]]></author>
<title><![CDATA[#[subject]#]]></title>
<category>#[category]#</category>
<link>http://#[peerAddress]#/Messages_p.html?action=view&amp;object=#[key]#</link>
<link>#[context]#/Messages_p.html?action=view&amp;object=#[key]#</link>
<pubDate>#[rfc822Date]#</pubDate>
<guid>#[key]#</guid>
<description><![CDATA[#[body]#]]></description>

View File

@ -169,8 +169,7 @@ public class ViewProfile {
prop.put("success_" + key, "1");
// only comments get "wikified"
if(key.equals("comment")){
prop.putWiki(sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP()),
"success_" + key + "_value",
prop.putWiki("success_" + key + "_value",
entry.getValue().replaceAll("\r", "").replaceAll("\\\\n", "\n"));
prop.put("success_" + key + "_b64value", Base64Order.standardCoder.encodeString(entry.getValue()));
}else{

View File

@ -37,7 +37,6 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import net.yacy.cora.document.encoding.UTF8;
import net.yacy.cora.protocol.Domains;
@ -129,18 +128,6 @@ public class Wiki {
prop.put(serverObjects.ACTION_LOCATION, prop.get(serverObjects.ACTION_LOCATION));
}
String hostAndPort = null;
Set<String> ips = null;
if(sb.peers.mySeed() != null) {
ips = sb.peers.mySeed().getIPs();
}
if(ips != null && !ips.isEmpty()) {
hostAndPort = sb.peers.mySeed().getPublicAddress(ips.iterator().next());
}
if (hostAndPort == null) {
hostAndPort = Domains.LOCALHOST + ":" + sb.getLocalPort();
}
if (post != null && post.containsKey("edit")) {
if ((access.equals("admin") && (!sb.verifyAuthentication(header)))) {
// check access right for admin
@ -160,8 +147,9 @@ public class Wiki {
prop.putHTML("mode_pagename", pagename);
prop.putHTML("mode_author", author);
prop.put("mode_date", dateString(new Date()));
// Note : it would be better to not only pass the peer host and port but also the protocol (http or https)
prop.putWiki(hostAndPort, "mode_page", post.get("content", ""));
/* We do not fill hostport parameter : relative links should stay relative as it is more reliable
* when the peer is behind any kind of reverse Proxy */
prop.putWiki("mode_page", post.get("content", ""));
prop.putHTML("mode_page-code", post.get("content", ""));
}
//end contrib of [MN]
@ -251,7 +239,9 @@ public class Wiki {
prop.putHTML("mode_versioning_pagename", pagename);
prop.putHTML("mode_versioning_author", oentry.author());
prop.put("mode_versioning_date", dateString(oentry.date()));
prop.putWiki(hostAndPort, "mode_versioning_page", oentry.page());
/* We do not fill hostport parameter : relative links should stay relative as it is more reliable
* when the peer is behind any kind of reverse Proxy */
prop.putWiki("mode_versioning_page", oentry.page());
prop.putHTML("mode_versioning_page-code", UTF8.String(oentry.page()));
}
} catch (final IOException e) {
@ -266,7 +256,9 @@ public class Wiki {
prop.putHTML("mode_pagename", pagename);
prop.putHTML("mode_author", page.author());
prop.put("mode_date", dateString(page.date()));
prop.putWiki(hostAndPort, "mode_page", page.page());
/* We do not fill hostport parameter : relative links should stay relative as it is more reliable
* when the peer is behind any kind of reverse Proxy */
prop.putWiki("mode_page", page.page());
prop.put("controls", "0");
prop.putHTML("controls_pagename", pagename);

View File

@ -70,7 +70,7 @@ public class mediawiki_p {
page = page.substring(p, q);
prop.putHTML("title", title);
prop.putWiki(sb.peers.mySeed().getPublicAddress(sb.peers.mySeed().getIP()), "page", page);
prop.putWiki("page", page);
return prop;
}

View File

@ -578,7 +578,7 @@ public class WikiCode extends AbstractWikiParser implements WikiParser {
/**
* Processes tags which are connected to links and images.
* @author [AS], [MN]
* @param hostport
* @param hostport (optional) host and port, added when not empty as the base of relative Wiki link URLs.
* @param line line of text to be transformed from wiki code to HTML
* @return HTML fragment
*/
@ -630,12 +630,12 @@ public class WikiCode extends AbstractWikiParser implements WikiParser {
}
}
// replace incomplete URLs and make them point to http://peerip:port/...
// eventually replace incomplete URLs and make them point to http://peerip:port/...
// with this feature you can access an image in DATA/HTDOCS/share/yacy.gif
// using the wikicode [[Image:share/yacy.gif]]
// or an image DATA/HTDOCS/grafics/kaskelix.jpg with [[Image:grafics/kaskelix.jpg]]
// you are free to use other sub-paths of DATA/HTDOCS
if (kl.indexOf("://",0) < 1) {
if (kl.indexOf("://",0) < 1 && hostport != null && !hostport.isEmpty()) {
kl = "http://" + hostport + "/" + kl;
}
@ -677,12 +677,12 @@ public class WikiCode extends AbstractWikiParser implements WikiParser {
else {
kv = kl;
}
// replace incomplete URLs and make them point to http://peerip:port/...
// eventually replace incomplete URLs and make them point to http://peerip:port/...
// with this feature you can access a file at DATA/HTDOCS/share/page.html
// using the wikicode [share/page.html]
// or a file DATA/HTDOCS/www/page.html with [www/page.html]
// you are free to use other sub-paths of DATA/HTDOCS
if (kl.indexOf("://",0) < 1) {
if (kl.indexOf("://",0) < 1 && hostport != null && !hostport.isEmpty()) {
kl = "http://" + hostport + "/" + kl;
}
line = line.substring(0, positionOfOpeningTag) + "<a class=\"extern\" href=\"" + kl + "\">" + kv + "</a>" + line.substring(positionOfClosingTag + LEN_WIKI_CLOSE_EXTERNAL_LINK);

View File

@ -352,10 +352,31 @@ public class serverObjects implements Serializable, Cloneable {
}
/**
* Add a String to the map. The content of the String is first parsed and interpreted as Wiki code.
* @param hostport (optional) peer host and port, added when not empty as the base of relative Wiki link URLs.
* @param key key name as String.
* @param wikiCode wiki code content as String.
*/
public void putWiki(final String hostport, final String key, final String wikiCode){
this.put(key, Switchboard.wikiParser.transform(hostport, wikiCode));
}
/**
* Add a String to the map. The content of the String is first parsed and interpreted as Wiki code.
* @param key key name as String.
* @param wikiCode wiki code content as String.
*/
public void putWiki(final String key, final String wikiCode){
this.putWiki(null, key, wikiCode);
}
/**
* Add a byte array to the map. The content of the array is first parsed and interpreted as Wiki code.
* @param hostport (optional) peer host and port, added when not empty as the base of relative Wiki link URLs.
* @param key key name as String.
* @param wikiCode wiki code content as byte array.
*/
public void putWiki(final String hostport, final String key, final byte[] wikiCode) {
try {
this.put(key, Switchboard.wikiParser.transform(hostport, wikiCode));
@ -363,6 +384,15 @@ public class serverObjects implements Serializable, Cloneable {
this.put(key, "Internal error pasting wiki-code: " + e.getMessage());
}
}
/**
* Add a byte array to the map. The content of the array is first parsed and interpreted as Wiki code.
* @param key key name as String.
* @param wikiCode wiki code content as byte array.
*/
public void putWiki(final String key, final byte[] wikiCode) {
this.putWiki(null, key, wikiCode);
}
// inc variant: for counters
public long inc(final String key) {