// dir.java // ----------------------- // part of the AnomicHTTPD caching proxy // (C) by Michael Peter Christen; mc@anomic.de // first published on http://www.anomic.de // Frankfurt, Germany, 2004, 2005 // // $LastChangedDate$ // $LastChangedRevision$ // $LastChangedBy$ // // 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 // // Using this software in any meaning (reading, learning, copying, compiling, // running) means that you agree that the Author(s) is (are) not responsible // for cost, loss of data or any harm that may be caused directly or indirectly // by usage of this softare or this documentation. The usage of this software // is on your own risk. The installation and usage (starting/running) of this // software may allow other people or application to access your computer and // any attached devices and is highly dependent on the configuration of the // software which must be done by the user of the software; the author(s) is // (are) also not responsible for proper configuration and usage of the // software, even if provoked by documentation provided together with // the software. // // Any changes to this file according to the GPL as documented in the file // gpl.txt aside this file in the shipment you received can be done to the // lines that follows this copyright notice here, but changes must not be // done inside the copyright notive above. A re-distribution must contain // the intact and unchanged copyright notice. // Contributions and changes to the program code must be marked as such. // // You must compile this file with // javac -classpath /classes /htroot/htdocsdefault/dir.java // which most probably means to compile this with // javac -classpath ../../classes dir.java import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.net.URL; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Set; import java.net.InetAddress; import java.net.UnknownHostException; import de.anomic.http.httpHeader; import de.anomic.plasma.plasmaCondenser; import de.anomic.plasma.plasmaCrawlLURL; import de.anomic.plasma.plasmaSwitchboard; import de.anomic.plasma.plasmaURL; import de.anomic.plasma.plasmaWordIndexEntry; import de.anomic.server.serverCodings; import de.anomic.server.serverCore; import de.anomic.server.serverFileUtils; import de.anomic.server.serverObjects; import de.anomic.server.serverSwitch; import de.anomic.server.logging.serverLog; import de.anomic.yacy.yacyCore; import de.anomic.yacy.yacySeed; import de.anomic.data.userDB; public class dir { private static SimpleDateFormat SimpleFormatter = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); public static String dateString(Date date) { return SimpleFormatter.format(date); } public static serverObjects respond(httpHeader header, serverObjects post, serverSwitch env) { final plasmaSwitchboard switchboard = (plasmaSwitchboard) env; final serverObjects prop = new serverObjects(); // System.out.println("###Header="+ header); // System.out.println("###post=" + post); String action = ((post == null) ? "info" : post.get("action", "info")); String tree = ""; // variables for this path // File htroot = new File(switchboard.getRootPath(), switchboard.getConfig("htRootPath", "htroot")); final File htroot = new File(switchboard.getRootPath(), switchboard.getConfig("htDocsPath", "DATA/HTDOCS")); String path = (String) header.get("PATH", "/"); int pos = path.lastIndexOf("/"); if (pos >= 0) { path = path.substring(0, pos + 1); } final File dir = new File(htroot, path); // general settings prop.put("peername", env.getConfig("peerName", "")); prop.put("peerdomain", env.getConfig("peerName", "").toLowerCase()); prop.put("peeraddress", yacyCore.seedDB.mySeed.getAddress()); prop.put("hostname", serverCore.publicIP()); try{ prop.put("hostip", InetAddress.getByName(serverCore.publicIP()).getHostAddress()); }catch(UnknownHostException e){ prop.put("hostip", "Unknown Host Exception"); } prop.put("port", env.getConfig("port", "8080")); // generate upload/download authorizations final String adminAccountBase64MD5 = switchboard.getConfig("adminAccountBase64MD5", ""); final String uploadAccountBase64MD5 = switchboard.getConfig("uploadAccountBase64MD5", ""); final String downloadAccountBase64MD5 = switchboard.getConfig("downloadAccountBase64MD5", ""); final String logoutAccountBase64MD5 = de.anomic.server.serverCodings.encodeMD5Hex(serverCodings.standardCoder.encodeBase64String(":")); userDB.Entry entry = switchboard.userDB.proxyAuth((String)header.get("Authorization", "xxxxxx")); boolean adminAuthorization, downloadAuthorization, uploadAuthorization; if(entry == null){ final String authorizationMD5 = de.anomic.server.serverCodings.encodeMD5Hex(((String) header.get("Authorization", "xxxxxx")).trim().substring(6)); // if (logoutAccountBase64.equals(authorization)) adminAuthorization = (adminAccountBase64MD5.length() != 0 && adminAccountBase64MD5.equals(authorizationMD5)); uploadAuthorization = (adminAuthorization ||(uploadAccountBase64MD5.length() != 0 && uploadAccountBase64MD5.equals(authorizationMD5))); downloadAuthorization = (adminAuthorization || uploadAuthorization || downloadAccountBase64MD5.length() == 0 || downloadAccountBase64MD5.equals(authorizationMD5)); }else{ //userDB adminAuthorization=entry.hasAdminRight(); uploadAuthorization=entry.hasUploadRight(); downloadAuthorization=entry.hasDownloadRight(); } // do authentitcate processes by triggering the http authenticate method if (action.equals("authenticateAdmin") && !adminAuthorization) { prop.put("AUTHENTICATE", "admin log-in"); return prop; } if (action.equals("authenticateUpload") && !uploadAuthorization) { prop.put("AUTHENTICATE", "upload log-in"); return prop; } if (action.equals("authenticateDownload") && !downloadAuthorization) { prop.put("AUTHENTICATE", "download log-in"); return prop; } // work off actions if (action.equals("logout")) { if (adminAuthorization) { prop.put("AUTHENTICATE", "admin log-in"); return prop; } else if (uploadAuthorization) { prop.put("AUTHENTICATE", "upload log-in"); return prop; } else if (downloadAuthorization) { prop.put("AUTHENTICATE", "download log-in"); return prop; } else { action = ""; } } if (action.equals("downloadPassword") && adminAuthorization) { switchboard.setConfig("downloadAccountBase64MD5", (post.get("password", "").length() == 0) ? "" : serverCodings.standardCoder.encodeMD5Hex(serverCodings.standardCoder.encodeBase64String("download:" + post.get("password", "")))); } if (action.equals("uploadPassword") && adminAuthorization) { switchboard.setConfig("uploadAccountBase64MD5", (post.get("password", "").length() == 0) ? "" : serverCodings.standardCoder.encodeMD5Hex(serverCodings.standardCoder.encodeBase64String("upload:" + post.get("password", "")))); } if (action.equals("upload") && (uploadAuthorization || adminAuthorization)) { String filename = new File(post.get("file", "dummy")).getName(); String description = post.get("description", ""); pos = filename.lastIndexOf("\\"); if (pos >= 0) { filename = filename.substring(pos + 1); } final File newfile = new File(dir, filename); final File newfilemd5 = new File(dir, filename + ".md5"); final byte[] binary = (byte[]) post.get((Object) "file$file", (Object) new byte[0]); try { serverFileUtils.write(binary, newfile); String md5s = serverCodings.encodeMD5Hex(newfile); serverFileUtils.write((md5s + "\n" + description).getBytes(), newfilemd5); // generate md5 // index file info if (post.get("indexing", "").equals("on")) { final String urlstring = yacyhURL(yacyCore.seedDB.mySeed, filename, md5s); final String phrase = filename.replace('.', ' ').replace('_', ' ').replace('-', ' '); indexPhrase(switchboard, urlstring, phrase, description); } } catch (IOException e) {} } if (action.equals("newdir") && (uploadAuthorization || adminAuthorization)) { final String newdirname = post.get("directory", "EmptyDir"); if (newdirname != null && newdirname.length() > 0) { final File newdir = new File(dir, newdirname); newdir.mkdir(); try { serverFileUtils.copy(new File(dir,"dir.html"), new File(newdir, "dir.html")); serverFileUtils.copy(new File(dir,"dir.class"), new File(newdir, "dir.class")); } catch (IOException e) {} } } if (action.equals("delete") && adminAuthorization) { String filename = post.get("file", "foo"); final File file = new File(dir, filename); if (file.exists()) { final File filemd5 = new File(dir, post.get("file", "foo") + ".md5"); // read md5 and phrase String md5s = ""; String description = ""; if (filemd5.exists()) try { md5s = new String(serverFileUtils.read(filemd5)); pos = md5s.indexOf('\n'); if (pos >= 0) { description = md5s.substring(pos + 1); md5s = md5s.substring(0, pos); } } catch (IOException e) {} // delete file(s) if (file.isDirectory()) { final String[] content = file.list(); for (int i = 0; i < content.length; i++) (new File(file, content[i])).delete(); file.delete(); } else if (file.isFile()) { file.delete(); if (filemd5.exists()) filemd5.delete(); } // delete index final String urlstring = yacyhURL(yacyCore.seedDB.mySeed, filename, md5s); final String phrase = filename.replace('.', ' ').replace('_', ' ').replace('-', ' '); deletePhrase(switchboard, urlstring, phrase, description); } } // if authorized, generate directory tree listing if ((adminAuthorization) || (uploadAuthorization) || (downloadAuthorization)) { // generate dir listing final String[] list = dir.list(); File f, fmd5; String md5s, description; Date d; // tree += "path = " + path + "

"; if (list == null) tree += "This directory is empty.
"; else { int filecount = 0; tree += "" + ""; boolean dark = false; for (int i = 0; i < list.length; i++) { if (!((list[i].startsWith("dir.")) || (list[i].endsWith(".md5")))) { tree += ""; dark = !dark; filecount++; f = new File(dir, list[i]); fmd5 = new File(dir, list[i] + ".md5"); try { if (fmd5.exists()) { md5s = new String(serverFileUtils.read(fmd5)); pos = md5s.indexOf('\n'); if (pos >= 0) { description = md5s.substring(pos + 1); md5s = md5s.substring(0, pos); } else { description = ""; } } else { // generate md5 on-the-fly md5s = serverCodings.encodeMD5Hex(f); description = ""; serverFileUtils.write((md5s + "\n" + description).getBytes(), fmd5); } } catch (IOException e) { md5s = ""; description = ""; } d = new Date(f.lastModified()); if (f.isDirectory()) { tree += ""; tree += ""; tree += ""; tree += ""; tree += ""; } else { tree += ""; tree += ""; tree += ""; tree += ""; } // if (adminAuthorization) tree += " "; else tree += "
"; tree += "" + serverCore.crlfString; } } tree += "
" + path + "
" + dateString(d) + "" + list[i] + "" + formatLong(0, 10) + "Directory"; tree += "" + dateString(d) + " "; tree += "" + list[i] + "" + formatLong(f.length(), 10) + "" + md5s + "" + (((description.length() == 0) && ((list[i].endsWith(".jpg")) || (list[i].endsWith(".gif")) || (list[i].endsWith(".png")))) ? (""; } if (adminAuthorization) { tree += "" + "
" + "" + "" + "
"; if (filecount == 0) { tree += "EMPTY
"; } } } String ident = ""; String account = ""; String service = ""; String info = ""; String logout = ""; if (adminAuthorization) { ident = "Administrator"; account = "" + "" + "" + "
upload:
" + "" + " " + "" + "
download:
" + "" + " " + "" + "
"; logout = "
" + "" + " (enter empty account)" + "
"; service = "" + "" + "" + "" + "" + "" + "" + "
New Directory:
" + "" + " " + "" + "
File Upload:
" + "Resource = " + "
" + "Description = 
" + "Indexing : 
" + "" + "
"; info = "Admin and download accounts are necessary to grant their services to clients; " + "no password is required for the download-account unless you set one. " + "Files uploaded and indexed here have a special index entry 'yacyshare'; " + "if you want to find files that are indexed in any share zone, add the word 'yacyshare' to the search words."; } else if (uploadAuthorization) { ident = "Uploader"; account = "
" + "" + "" + "
"; if (uploadAccountBase64MD5.length() == 0) { logout = ""; } else { logout = "
" + "" + " (enter empty account)" + "
"; } service = "" + "" + "" + "" + "" + "" + "" + "
New Directory:
" + "" + " " + "" + "
File Upload:
" + "Resource = " + "
" + "Description = 
" + "Indexing : 
" + "" + "
"; info = "Uploaders are not granted to delete files or directories. If you want to do this, log-in as admin."; } else if (downloadAuthorization) { ident = "Downloader"; account = "
" + "" + "" + "
" + "
" + "" + "" + "
"; if (downloadAccountBase64MD5.length() == 0) { logout = ""; } else { logout = "
" + "" + " (enter empty account)" + "
"; service = "You are granted to view directory listings and do downloads in this directory.
" + "If you want to upload, please log in as user 'upload'"; info = "Download is granted even if no download account has been defined. " + "If you are an administrator and you wish to block non-authorized downloades, please log in as user 'admin' " + "and set a download password."; } } else { ident = "not authorized"; tree = "To inspect this directory you need either an admin, upload or download account. Please log in."; account = "
" + "" + "" + "
" + "
" + "" + "" + "
" + "
" + "" + "" + "
"; logout = ""; service = "No service available."; info = "You must log-in to upload or download."; } prop.put("dir", tree); prop.put("ident", ident); prop.put("account", account); prop.put("service", service); prop.put("info", info); prop.put("logout", logout); // return rewrite properties return prop; } private static String formatLong(long l, int length) { String r = "" + l; for (int i = r.length(); i < length; i++) { r = " " + r; } return r; } // rDNS services: // http://www.xdr2.net/reverse_DNS_lookup.asp // http://remote.12dt.com/rns/ // http://bl.reynolds.net.au/search/ // http://www.declude.com/Articles.asp?ID=97 // http://www.dnsstuff.com/ // listlist: http://www.aspnetimap.com/help/welcome/dnsbl.html public static String yacyhURL(yacySeed seed, String filename, String md5) { return "http://share." + seed.getHexHash() + ".yacyh/" + filename + "?md5=" + md5; } public static void indexPhrase(plasmaSwitchboard switchboard, String urlstring, String phrase, String descr) { try { final URL url = new URL(urlstring); final plasmaCondenser condenser = new plasmaCondenser(new ByteArrayInputStream(("yacyshare. " + phrase + ". " + descr).getBytes())); final plasmaCrawlLURL.Entry newEntry = switchboard.urlPool.loadedURL.addEntry( url, "YaCyShare: " + descr, new Date(), new Date(), "____________", /*initiator*/ yacyCore.seedDB.mySeed.hash, /*executor*/ "AAAAAAAAAAAA", /*referrer*/ 0, /*copycount*/ false, /*localneed*/ Integer.parseInt(condenser.getAnalysis().getProperty("INFORMATION_VALUE","0"), 16), "**", /*language*/ plasmaWordIndexEntry.DT_SHARE, /*doctype*/ phrase.length(), /*size*/ (int) Long.parseLong(condenser.getAnalysis().getProperty("NUMB_WORDS","0"), 16), 5 /*process case*/ ); final String urlHash = newEntry.hash(); final int words = switchboard.wordIndex.addPageIndex(url, urlHash, new Date(), condenser, "**", plasmaWordIndexEntry.DT_SHARE); } catch (IOException e) {} } public static void deletePhrase(plasmaSwitchboard switchboard, String urlstring, String phrase, String descr) { try { final String urlhash = plasmaURL.urlHash(new URL(urlstring)); final Set words = plasmaCondenser.getWords(("yacyshare " + phrase + " " + descr).getBytes()); switchboard.removeReferences(urlhash, words); switchboard.urlPool.loadedURL.remove(urlhash); } catch (Exception e) { serverLog.logSevere("DIR", "INTERNAL ERROR in dir.deletePhrase", e); } } }