001: //yacySeedUploadScp.java
002: //-------------------------------------
003: //part of YACY
004: //(C) by Michael Peter Christen; mc@anomic.de
005: //first published on http://www.anomic.de
006: //Frankfurt, Germany, 2004
007: //
008: //This file ist contributed by Martin Thelian
009: //last major change: $LastChangedDate: 2006-03-08 16:34:05 +0000 (Mi, 08 Mrz 2006) $ by $LastChangedBy: theli $
010: //Revision: $LastChangedRevision: 1861 $
011: //
012: //This program is free software; you can redistribute it and/or modify
013: //it under the terms of the GNU General Public License as published by
014: //the Free Software Foundation; either version 2 of the License, or
015: //(at your option) any later version.
016: //
017: //This program is distributed in the hope that it will be useful,
018: //but WITHOUT ANY WARRANTY; without even the implied warranty of
019: //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
020: //GNU General Public License for more details.
021: //
022: //You should have received a copy of the GNU General Public License
023: //along with this program; if not, write to the Free Software
024: //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
025: //
026: //Using this software in any meaning (reading, learning, copying, compiling,
027: //running) means that you agree that the Author(s) is (are) not responsible
028: //for cost, loss of data or any harm that may be caused directly or indirectly
029: //by usage of this softare or this documentation. The usage of this software
030: //is on your own risk. The installation and usage (starting/running) of this
031: //software may allow other people or application to access your computer and
032: //any attached devices and is highly dependent on the configuration of the
033: //software which must be done by the user of the software; the author(s) is
034: //(are) also not responsible for proper configuration and usage of the
035: //software, even if provoked by documentation provided together with
036: //the software.
037: //
038: //Any changes to this file according to the GPL as documented in the file
039: //gpl.txt aside this file in the shipment you received can be done to the
040: //lines that follows this copyright notice here, but changes must not be
041: //done inside the copyright notive above. A re-distribution must contain
042: //the intact and unchanged copyright notice.
043: //Contributions and changes to the program code must be marked as such.
044:
045: package de.anomic.yacy.seedUpload;
046:
047: import java.io.BufferedInputStream;
048: import java.io.File;
049: import java.io.FileInputStream;
050: import java.io.IOException;
051: import java.io.InputStream;
052: import java.io.OutputStream;
053:
054: import com.jcraft.jsch.Channel;
055: import com.jcraft.jsch.ChannelExec;
056: import com.jcraft.jsch.JSch;
057: import com.jcraft.jsch.Session;
058: import com.jcraft.jsch.UIKeyboardInteractive;
059: import com.jcraft.jsch.UserInfo;
060:
061: import de.anomic.server.serverSwitch;
062: import de.anomic.yacy.yacySeedDB;
063: import de.anomic.yacy.yacySeedUploader;
064:
065: public class yacySeedUploadScp implements yacySeedUploader {
066:
067: public static final String CONFIG_SCP_SERVER = "seedScpServer";
068: public static final String CONFIG_SCP_SERVER_PORT = "seedScpServerPort";
069: public static final String CONFIG_SCP_ACCOUNT = "seedScpAccount";
070: public static final String CONFIG_SCP_PASSWORD = "seedScpPassword";
071: public static final String CONFIG_SCP_PATH = "seedScpPath";
072:
073: public String uploadSeedFile(serverSwitch sb, yacySeedDB seedDB,
074: File seedFile) throws Exception {
075: try {
076: if (sb == null)
077: throw new NullPointerException(
078: "Reference to serverSwitch nut not be null.");
079: if (seedDB == null)
080: throw new NullPointerException(
081: "Reference to seedDB must not be null.");
082: if ((seedFile == null) || (!seedFile.exists()))
083: throw new Exception("Seed file does not exist.");
084:
085: String seedScpServer = sb
086: .getConfig(CONFIG_SCP_SERVER, null);
087: String seedScpServerPort = sb.getConfig(
088: CONFIG_SCP_SERVER_PORT, "22");
089: String seedScpAccount = sb.getConfig(CONFIG_SCP_ACCOUNT,
090: null);
091: String seedScpPassword = sb.getConfig(CONFIG_SCP_PASSWORD,
092: null);
093: String seedScpPath = sb.getConfig(CONFIG_SCP_PATH, null);
094:
095: if (seedScpServer == null || seedScpServer.length() == 0)
096: throw new Exception(
097: "Seed SCP upload settings not configured properly. Servername must not be null or empty.");
098: else if (seedScpAccount == null
099: || seedScpAccount.length() == 0)
100: throw new Exception(
101: "Seed SCP upload settings not configured properly. Username must not be null or empty.");
102: else if (seedScpPassword == null
103: || seedScpPassword.length() == 0)
104: throw new Exception(
105: "Seed SCP upload settings not configured properly. Password must not be null or empty.");
106: else if (seedScpPath == null || seedScpPath.length() == 0)
107: throw new Exception(
108: "Seed SCP upload settings not configured properly. File path must not be null or empty.");
109: else if (seedScpServerPort == null
110: || seedScpServerPort.length() == 0)
111: throw new Exception(
112: "Seed SCP upload settings not configured properly. Server port must not be null or empty.");
113: int port = 22;
114: try {
115: port = Integer.valueOf(seedScpServerPort).intValue();
116: } catch (NumberFormatException ex) {
117: throw new Exception(
118: "Seed SCP upload settings not configured properly. Server port is not a vaild integer.");
119: }
120:
121: return sshc.put(seedScpServer, port, seedFile, seedScpPath,
122: seedScpAccount, seedScpPassword);
123: } catch (Exception e) {
124: throw e;
125: }
126: }
127:
128: public String[] getConfigurationOptions() {
129: return new String[] { CONFIG_SCP_SERVER,
130: CONFIG_SCP_SERVER_PORT, CONFIG_SCP_ACCOUNT,
131: CONFIG_SCP_PASSWORD, CONFIG_SCP_PATH };
132: }
133:
134: public String[] getLibxDependencies() {
135: return new String[] { "jsch-0.1.21.jar" };
136: }
137:
138: }
139:
140: class sshc {
141: public static String put(String host, int port, File localFile,
142: String remoteName, String account, String password)
143: throws Exception {
144:
145: Session session = null;
146: try {
147: // Creating a new secure channel object
148: JSch jsch = new JSch();
149:
150: // setting hostname, username, userpassword
151: session = jsch.getSession(account, host, port);
152: session.setPassword(password);
153:
154: /*
155: * Setting the StrictHostKeyChecking to ignore unknown
156: * hosts because of a missing known_hosts file ...
157: */
158: java.util.Properties config = new java.util.Properties();
159: config.put("StrictHostKeyChecking", "no");
160: session.setConfig(config);
161:
162: /*
163: * we need this user interaction interface to support
164: * the interactive-keyboard mode
165: */
166: UserInfo ui = new SchUserInfo(password);
167: session.setUserInfo(ui);
168:
169: // trying to connect ...
170: session.connect();
171:
172: String command = "scp -p -t " + remoteName;
173: Channel channel = session.openChannel("exec");
174: ((ChannelExec) channel).setCommand(command);
175:
176: // get I/O streams for remote scp
177: OutputStream out = channel.getOutputStream();
178: InputStream in = channel.getInputStream();
179:
180: channel.connect();
181:
182: checkAck(in);
183:
184: // send "C0644 filesize filename", where filename should not include '/'
185: int filesize = (int) (localFile).length();
186: command = "C0644 " + filesize + " ";
187: if (localFile.toString().lastIndexOf('/') > 0) {
188: command += localFile.toString().substring(
189: localFile.toString().lastIndexOf('/') + 1);
190: } else {
191: command += localFile.toString();
192: }
193: command += "\n";
194: out.write(command.getBytes());
195: out.flush();
196:
197: checkAck(in);
198:
199: // send a content of lfile
200: byte[] buf = new byte[1024];
201: BufferedInputStream bufferedIn = null;
202: try {
203: bufferedIn = new BufferedInputStream(
204: new FileInputStream(localFile));
205: while (true) {
206: int len = bufferedIn.read(buf, 0, buf.length);
207: if (len <= 0)
208: break;
209: out.write(buf, 0, len);
210: out.flush();
211: }
212: } finally {
213: if (bufferedIn != null)
214: try {
215: bufferedIn.close();
216: } catch (Exception e) {
217: }
218: }
219:
220: // send '\0'
221: buf[0] = 0;
222: out.write(buf, 0, 1);
223: out.flush();
224:
225: checkAck(in);
226:
227: return "SCP: File uploaded successfully.";
228: } catch (Exception e) {
229: throw new Exception("SCP: File uploading failed: "
230: + e.getMessage());
231: } finally {
232: if ((session != null) && (session.isConnected()))
233: session.disconnect();
234: }
235: }
236:
237: static int checkAck(InputStream in) throws IOException {
238: int b = in.read();
239: // b may be 0 for success,
240: // 1 for error,
241: // 2 for fatal error,
242: // -1
243: if (b == 0)
244: return b;
245: if (b == -1)
246: return b;
247:
248: if (b == 1 || b == 2) {
249: StringBuffer sb = new StringBuffer();
250: int c;
251: do {
252: c = in.read();
253: sb.append((char) c);
254: } while (c != '\n');
255:
256: if (b == 1) { // error
257: throw new IOException(sb.toString());
258: }
259: if (b == 2) { // fatal error
260: throw new IOException(sb.toString());
261: }
262: }
263: return b;
264: }
265: }
266:
267: class SchUserInfo implements UserInfo, UIKeyboardInteractive {
268: String passwd;
269:
270: public SchUserInfo(String password) {
271: this .passwd = password;
272: }
273:
274: public String getPassword() {
275: return this .passwd;
276: }
277:
278: public boolean promptYesNo(String str) {
279: System.err.println("User was prompted from: " + str);
280: return true;
281: }
282:
283: public String getPassphrase() {
284: return null;
285: }
286:
287: public boolean promptPassphrase(String message) {
288: System.out.println("promptPassphrase : " + message);
289: return false;
290: }
291:
292: public boolean promptPassword(String message) {
293: System.out.println("promptPassword : " + message);
294: return true;
295: }
296:
297: /**
298: * @see com.jcraft.jsch.UserInfo#showMessage(java.lang.String)
299: */
300: public void showMessage(String message) {
301: System.out
302: .println("Sch has tried to show the following message to the user: "
303: + message);
304: }
305:
306: public String[] promptKeyboardInteractive(String destination,
307: String name, String instruction, String[] prompt,
308: boolean[] echo) {
309: System.out
310: .println("User was prompted using interactive-keyboard: "
311: + "\n\tDestination: "
312: + destination
313: + "\n\tName: "
314: + name
315: + "\n\tInstruction: "
316: + instruction
317: + "\n\tPrompt: "
318: + arrayToString2(prompt, "|")
319: + "\n\techo: "
320: + arrayToString2(echo, "|"));
321:
322: if ((prompt.length >= 1) && (prompt[0].startsWith("Password")))
323: return new String[] { this .passwd };
324: return new String[] {};
325: }
326:
327: String arrayToString2(String[] a, String separator) {
328: StringBuffer result = new StringBuffer();// start with first element
329: if (a.length > 0) {
330: result.append(a[0]);
331: for (int i = 1; i < a.length; i++) {
332: result.append(separator);
333: result.append(a[i]);
334: }
335: }
336: return result.toString();
337: }
338:
339: String arrayToString2(boolean[] a, String separator) {
340: StringBuffer result = new StringBuffer();// start with first element
341: if (a.length > 0) {
342: result.append(a[0]);
343: for (int i = 1; i < a.length; i++) {
344: result.append(separator);
345: result.append(a[i]);
346: }
347: }
348: return result.toString();
349: }
350: }
|