2005-11-11 09:02:46 +01:00
// transfer.java
// -----------------------
// part of YaCy caching proxy
2008-07-20 19:14:51 +02:00
// (C) by Michael Peter Christen; mc@yacy.net
2005-11-11 09:02:46 +01:00
// first published on http://www.anomic.de
// Frankfurt, Germany, 2004
// created 07.11.2005
//
2006-01-18 01:03:28 +01:00
// $LastChangedDate$
// $LastChangedRevision$
// $LastChangedBy$
2005-11-11 09:02:46 +01:00
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import java.io.File ;
import java.io.IOException ;
2008-08-25 20:11:47 +02:00
import de.anomic.http.httpRequestHeader ;
2009-01-30 23:08:08 +01:00
import de.anomic.kelondro.order.Base64Order ;
import de.anomic.kelondro.order.Digest ;
2009-01-31 02:06:56 +01:00
import de.anomic.kelondro.util.FileUtils ;
2005-11-11 09:02:46 +01:00
import de.anomic.plasma.plasmaRankingDistribution ;
2006-09-30 00:27:20 +02:00
import de.anomic.plasma.plasmaSwitchboard ;
2005-11-11 09:02:46 +01:00
import de.anomic.server.serverObjects ;
import de.anomic.server.serverSwitch ;
2007-07-05 01:48:52 +02:00
import de.anomic.yacy.yacyNetwork ;
2005-11-11 09:02:46 +01:00
import de.anomic.yacy.yacySeed ;
public final class transfer {
2008-08-25 20:11:47 +02:00
public static serverObjects respond ( final httpRequestHeader header , final serverObjects post , final serverSwitch < ? > env ) {
2008-08-02 14:12:04 +02:00
final plasmaSwitchboard sb = ( plasmaSwitchboard ) env ;
final serverObjects prop = new serverObjects ( ) ;
2008-03-12 01:05:18 +01:00
if ( ( post = = null ) | | ( env = = null ) ) return prop ;
if ( ! yacyNetwork . authentifyRequest ( post , env ) ) return prop ;
2008-08-02 14:12:04 +02:00
final String process = post . get ( " process " , " " ) ; // permission or store
2008-03-12 01:05:18 +01:00
//String key = post.get("key", ""); // a transmission key from the client
2008-08-02 14:12:04 +02:00
final String otherpeer = post . get ( " iam " , " " ) ; // identification of the client (a peer-hash)
final String purpose = post . get ( " purpose " , " " ) ; // declares how the file shall be treated
final String filename = post . get ( " filename " , " " ) ; // a name of a file without path
2008-03-12 01:05:18 +01:00
//long filesize = Long.parseLong((String) post.get("filesize", "")); // the size of the file
2006-01-18 03:18:23 +01:00
2007-10-24 23:38:19 +02:00
prop . put ( " process " , " 0 " ) ;
prop . put ( " response " , " denied " ) ; // reject is default and is overwritten if ok
prop . put ( " process_access " , " " ) ;
prop . put ( " process_address " , " " ) ;
prop . put ( " process_protocol " , " " ) ;
prop . put ( " process_path " , " " ) ;
prop . put ( " process_maxsize " , " 0 " ) ;
2006-01-18 03:18:23 +01:00
2008-02-05 17:54:45 +01:00
if ( sb . isRobinsonMode ( ) | | ! sb . rankingOn ) {
2008-03-12 01:05:18 +01:00
// in a robinson environment, do not answer. We do not do any transfer in a robinson cluster.
return prop ;
2007-04-24 17:11:12 +02:00
}
2006-01-18 03:18:23 +01:00
2009-03-13 11:34:51 +01:00
final yacySeed otherseed = sb . webIndex . peers ( ) . get ( otherpeer ) ;
2008-03-12 01:05:18 +01:00
if ( ( otherseed = = null ) | | ( filename . indexOf ( " .. " ) > = 0 ) ) {
2006-01-17 23:19:18 +01:00
// reject unknown peers: this does not appear fair, but anonymous senders are dangerous
// reject paths that contain '..' because they are dangerous
2008-09-03 02:30:21 +02:00
if ( sb . getLog ( ) . isFine ( ) ) {
if ( otherseed = = null ) sb . getLog ( ) . logFine ( " RankingTransmission: rejected unknown peer ' " + otherpeer + " ', current IP " + header . get ( httpRequestHeader . CONNECTION_PROP_CLIENTIP , " unknown " ) ) ;
if ( filename . indexOf ( " .. " ) > = 0 ) sb . getLog ( ) . logFine ( " RankingTransmission: rejected wrong path ' " + filename + " ' from peer " + ( otherseed = = null ? " null " : otherseed . getName ( ) + " / " + otherseed . getPublicAddress ( ) ) + " , current IP " + header . get ( httpRequestHeader . CONNECTION_PROP_CLIENTIP , " unknown " ) ) ;
}
2005-11-11 09:02:46 +01:00
return prop ;
}
2008-03-12 01:05:18 +01:00
2008-08-02 14:12:04 +02:00
final String otherpeerName = otherseed . hash + " : " + otherseed . getName ( ) ;
2008-03-12 01:05:18 +01:00
2005-11-11 09:02:46 +01:00
if ( process . equals ( " permission " ) ) {
2007-10-24 23:38:19 +02:00
prop . put ( " process " , " 0 " ) ;
2006-03-13 21:12:31 +01:00
if ( ( ( purpose . equals ( " crcon " ) ) & & ( filename . startsWith ( " CRG " ) ) & & ( filename . endsWith ( " .cr.gz " ) ) ) | | ( ( filename . startsWith ( " domlist " ) ) & & ( filename . endsWith ( " .txt.gz " ) | | filename . endsWith ( " .zip " ) ) ) ) {
2005-11-11 09:02:46 +01:00
// consolidation of cr files
//System.out.println("yacy/transfer:post=" + post.toString());
2005-12-05 10:13:13 +01:00
//String cansendprotocol = (String) post.get("can-send-protocol", "http");
2009-01-30 16:33:00 +01:00
final String access = Base64Order . enhancedCoder . encode ( Digest . encodeMD5Raw ( otherpeer + " : " + filename ) ) + " : " + Base64Order . enhancedCoder . encode ( Digest . encodeMD5Raw ( " " + System . currentTimeMillis ( ) ) ) ;
2007-10-24 23:38:19 +02:00
prop . put ( " response " , " ok " ) ;
prop . put ( " process_access " , access ) ;
2009-03-13 11:34:51 +01:00
prop . put ( " process_address " , sb . webIndex . peers ( ) . mySeed ( ) . getPublicAddress ( ) ) ;
2007-10-24 23:38:19 +02:00
prop . put ( " process_protocol " , " http " ) ;
prop . put ( " process_path " , " " ) ; // currently empty; the store process will find a path
prop . put ( " process_maxsize " , " -1 " ) ; // if response is too big we return the size of the file
2009-01-30 16:33:00 +01:00
sb . rankingPermissions . put ( Digest . encodeMD5Hex ( Base64Order . standardCoder . encodeString ( access ) ) , filename ) ;
2008-09-03 02:30:21 +02:00
if ( sb . getLog ( ) . isFine ( ) ) sb . getLog ( ) . logFine ( " RankingTransmission: granted peer " + otherpeerName + " to send CR file " + filename ) ;
2005-11-11 09:02:46 +01:00
}
return prop ;
}
if ( process . equals ( " store " ) ) {
2007-10-24 23:38:19 +02:00
prop . put ( " process " , " 1 " ) ;
2005-11-11 09:02:46 +01:00
if ( purpose . equals ( " crcon " ) ) {
2008-08-02 14:12:04 +02:00
final String fileString = post . get ( " filename$file " ) ;
final String accesscode = post . get ( " access " , " " ) ; // one-time authentication
final String md5 = post . get ( " md5 " , " " ) ; // one-time authentication
2005-12-05 01:17:12 +01:00
//java.util.HashMap perm = sb.rankingPermissions;
2005-11-11 09:02:46 +01:00
//System.out.println("PERMISSIONDEBUG: accesscode=" + accesscode + ", permissions=" + perm.toString());
2008-08-02 14:12:04 +02:00
final String grantedFile = sb . rankingPermissions . get ( accesscode ) ;
2007-10-24 23:38:19 +02:00
prop . put ( " process_tt " , " " ) ;
2005-11-11 09:02:46 +01:00
if ( ( grantedFile = = null ) | | ( ! ( grantedFile . equals ( filename ) ) ) ) {
// fraud-access of this interface
2007-10-24 23:38:19 +02:00
prop . put ( " response " , " denied " ) ;
2008-09-03 02:30:21 +02:00
if ( sb . getLog ( ) . isFine ( ) ) sb . getLog ( ) . logFine ( " RankingTransmission: denied " + otherpeerName + " to send CR file " + filename + " : wrong access code " ) ;
2005-11-11 09:02:46 +01:00
} else {
sb . rankingPermissions . remove ( accesscode ) ; // not needed any more
2008-08-02 14:12:04 +02:00
final File path = new File ( sb . rankingPath , plasmaRankingDistribution . CR_OTHER ) ;
2005-11-11 09:02:46 +01:00
path . mkdirs ( ) ;
2008-08-02 14:12:04 +02:00
final File file = new File ( path , filename ) ;
2005-11-11 09:02:46 +01:00
try {
2008-08-06 21:43:12 +02:00
if ( file . getCanonicalPath ( ) . startsWith ( path . getCanonicalPath ( ) ) ) {
2009-01-31 02:06:56 +01:00
FileUtils . copy ( fileString . getBytes ( ) , file ) ;
2009-01-30 16:33:00 +01:00
final String md5t = Digest . encodeMD5Hex ( file ) ;
2006-01-17 20:01:20 +01:00
if ( md5t . equals ( md5 ) ) {
2007-10-24 23:38:19 +02:00
prop . put ( " response " , " ok " ) ;
2008-09-03 02:30:21 +02:00
if ( sb . getLog ( ) . isFine ( ) ) sb . getLog ( ) . logFine ( " RankingTransmission: received from peer " + otherpeerName + " CR file " + filename ) ;
2006-01-17 20:01:20 +01:00
} else {
2007-10-24 23:38:19 +02:00
prop . put ( " response " , " transfer failure " ) ;
2008-09-03 02:30:21 +02:00
if ( sb . getLog ( ) . isFine ( ) ) sb . getLog ( ) . logFine ( " RankingTransmission: transfer failure from peer " + otherpeerName + " for CR file " + filename ) ;
2006-01-17 20:01:20 +01:00
}
} else {
//exploit?
2007-10-24 23:38:19 +02:00
prop . put ( " response " , " io error " ) ;
2006-01-17 20:01:20 +01:00
return prop ;
2005-11-11 09:02:46 +01:00
}
2008-08-02 14:12:04 +02:00
} catch ( final IOException e ) {
2007-10-24 23:38:19 +02:00
prop . put ( " response " , " io error " ) ;
2005-11-11 09:02:46 +01:00
}
}
}
return prop ;
}
2006-01-18 03:18:23 +01:00
2005-11-11 09:02:46 +01:00
// wrong access
2008-09-03 02:30:21 +02:00
if ( sb . getLog ( ) . isFine ( ) ) sb . getLog ( ) . logFine ( " RankingTransmission: rejected unknown process " + process + " : " + purpose + " from peer " + otherpeerName ) ;
2005-11-11 09:02:46 +01:00
return prop ;
}
}