diff --git a/htroot/api/share.html b/htroot/api/share.html
new file mode 100644
index 000000000..fb7124061
--- /dev/null
+++ b/htroot/api/share.html
@@ -0,0 +1,47 @@
+
+
+
+
+ File Share
+ #(mode)#
+
+ This form can be used to share a (index) file
+
+ ::
+
+ Result for the recently submitted file(s). You can also submit the same form using the servlet share.json to get push confirmations in json format.
+
+ - successall
- #(successall)#false::true#(/successall)#
+ - countsuccess
- #[countsuccess]#
+ - countfail
- #[countfail]#
+
+
+ Item | URL | Success | Message |
+
+ #[item]# |
+ #[url]# |
+ #(success)#fail::ok#(/success)# |
+ #(success)##[message]#::#[message]##(/success)# |
+
+
+
+ If you want to push again files, use this form to pre-define a number of upload forms:
+
+
+ #(/mode)#
+
+
\ No newline at end of file
diff --git a/htroot/api/share.java b/htroot/api/share.java
new file mode 100644
index 000000000..a2deeb2ad
--- /dev/null
+++ b/htroot/api/share.java
@@ -0,0 +1,106 @@
+/**
+ * share
+ * Copyright 2016 by Michael Peter Christen, mc@yacy.net, Frankfurt a. M., Germany
+ * First released 24.02.2016 at http://yacy.net
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program in the file lgpl21.txt
+ * If not, see .
+ */
+
+import java.io.File;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+import net.yacy.yacy;
+import net.yacy.cora.document.encoding.UTF8;
+import net.yacy.cora.order.Base64Order;
+import net.yacy.cora.protocol.RequestHeader;
+import net.yacy.cora.util.ConcurrentLog;
+import net.yacy.search.Switchboard;
+import net.yacy.search.index.Fulltext;
+import net.yacy.server.serverObjects;
+import net.yacy.server.serverSwitch;
+
+public class share {
+
+ /**
+ * Servlet to share any kind of binary to this peer.
+ * That mean you can upload 'things'. While this is the generic view,
+ * it will operate in the beginning only for full solr export files.
+ * The servlet will decide if it wants that kind of data and if the sender is valid,
+ * i.e. if the sender is within the own network and known.
+ * Index dumps which are uploaded are placed to a specific folder
+ * where they can be downloaded again by peers.
+ * An optional operation is the immediate indexing of the shared index.
+ * @param header
+ * @param post
+ * @param env
+ * @return
+ */
+ public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
+ final serverObjects prop = new serverObjects();
+
+ // display mode: this only helps to display a nice input form for test cases
+ int c = post == null ? 1 : post.getInt("c", 0);
+ if (c > 0) {
+ prop.put("mode", 0);
+ return prop;
+ }
+
+ // push mode: this does a document upload
+ prop.put("mode", 1);
+ prop.put("success", 0);
+ if (post == null) return prop;
+
+ // check file name
+ String filename = post.get("data", "");
+ if (!filename.startsWith(Fulltext.yacy_dump_prefix) || !filename.endsWith(".xml.gz")) return prop;
+
+ // check data
+ String dataString = post.get("data$file", "");
+ if (dataString.length() == 0) return prop;
+ byte[] data;
+ if (filename.endsWith(".base64")) {
+ data = Base64Order.standardCoder.decode(dataString);
+ filename = filename.substring(0, filename.length() - 7);
+ } else {
+ data = UTF8.getBytes(dataString);
+ }
+ if (data == null || data.length == 0) return prop;
+
+ // modify the file name; ignore and replace the used transaction token
+ int ttp = filename.indexOf("_t");
+ if (ttp < 0) return prop;
+ if (filename.charAt(ttp + 3) != '.') return prop;
+ filename = filename.substring(0, ttp) + "_ts" + filename.substring(ttp + 3); // transaction token: 's' as 'shared'.
+
+ // process the data
+ File tmpFile = new File(yacy.shareDumpDefaultPath, filename + ".tmp");
+ File finalFile = new File(yacy.shareDumpDefaultPath, filename);
+ try {
+ Files.copy(new ByteArrayInputStream(data), tmpFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ tmpFile.renameTo(finalFile);
+ } catch (IOException e) {
+ ConcurrentLog.logException(e);
+ return prop;
+ }
+
+ prop.put("success", 1);
+ return prop;
+ }
+
+}
diff --git a/source/net/yacy/search/index/Fulltext.java b/source/net/yacy/search/index/Fulltext.java
index a8fbed860..dd3a659aa 100644
--- a/source/net/yacy/search/index/Fulltext.java
+++ b/source/net/yacy/search/index/Fulltext.java
@@ -627,6 +627,7 @@ public final class Fulltext {
public String getExt() {return this.ext;}
}
+ public final static String yacy_dump_prefix = "yacy_dump_";
public Export export(Fulltext.ExportFormat format, String filter, String query, final int maxseconds, File path, boolean dom, boolean text) throws IOException {
// modify query according to maxseconds
@@ -662,11 +663,11 @@ public final class Fulltext {
Object lastdateobject = lastdoc.getFieldValue(CollectionSchema.load_date_dt.getSolrFieldName());
Date firstdate = (Date) firstdateobject;
Date lastdate = (Date) lastdateobject;
- String s = new File(path, "yacy_dump_" +
+ String s = new File(path, yacy_dump_prefix +
"f" + GenericFormatter.FORMAT_SHORT_MINUTE.format(firstdate) + "_" +
"l" + GenericFormatter.FORMAT_SHORT_MINUTE.format(lastdate) + "_" +
"n" + GenericFormatter.FORMAT_SHORT_MINUTE.format(new Date(now)) + "_" +
- "c" + String.format("%1$012d", doccount)).getAbsolutePath();
+ "c" + String.format("%1$012d", doccount)).getAbsolutePath() + "_tc"; // the name ends with the transaction token ('c' = 'created')
// create export file name
if (s.indexOf('.',0) < 0) s += "." + format.getExt();
diff --git a/source/net/yacy/yacy.java b/source/net/yacy/yacy.java
index 8082850d8..6d6a715eb 100644
--- a/source/net/yacy/yacy.java
+++ b/source/net/yacy/yacy.java
@@ -114,6 +114,10 @@ public final class yacy {
public static final String hline = "-------------------------------------------------------------------------------";
public static final Semaphore shutdownSemaphore = new Semaphore(0);
+ public static File htDocsPath = null;
+ public static File shareDefaultPath = null;
+ public static File shareDumpDefaultPath = null;
+
/**
* a reference to the {@link Switchboard} created by the
* {@link yacy#startup(String, long, long)} method.
@@ -244,7 +248,7 @@ public final class yacy {
// create some directories
final File htRootPath = new File(appHome, sb.getConfig(SwitchboardConstants.HTROOT_PATH, SwitchboardConstants.HTROOT_PATH_DEFAULT));
mkdirIfNeseccary(htRootPath);
- final File htDocsPath = sb.getDataPath(SwitchboardConstants.HTDOCS_PATH, SwitchboardConstants.HTDOCS_PATH_DEFAULT);
+ htDocsPath = sb.getDataPath(SwitchboardConstants.HTDOCS_PATH, SwitchboardConstants.HTDOCS_PATH_DEFAULT);
mkdirIfNeseccary(htDocsPath);
//final File htTemplatePath = new File(homePath, sb.getConfig("htTemplatePath","htdocs"));
@@ -287,8 +291,10 @@ public final class yacy {
System.out.println("Error creating htdocs readme: " + e.getMessage());
}
- final File shareDefaultPath = new File(htDocsPath, "share");
+ shareDefaultPath = new File(htDocsPath, "share");
mkdirIfNeseccary(shareDefaultPath);
+ shareDumpDefaultPath = new File(shareDefaultPath, "dump");
+ mkdirIfNeseccary(shareDumpDefaultPath);
migration.migrate(sb, oldRev, newRev);