Inital commit

This commit is contained in:
Tilman
2011-10-26 10:11:42 +02:00
commit c0da376199
888 changed files with 44367 additions and 0 deletions
@@ -0,0 +1,74 @@
/*
* Created on 02.02.2005
*/
package uebung05.aufgabe02;
import java.io.IOException;
import java.net.*;
import sun.misc.BASE64Encoder;
/**
* Verbindet zu einer gegebenen URL und versucht, via "Basic Authentication Scheme"
* Zugriff auf die Ressource zu bekommen. Hierfür werden sämtliche Permutation
* vorgegebener Namen/Passworte durchgegangen
*
* @author Tilman Walther
*/
public class AuthCheck {
// die URL, auf die zugegriffen wird
String resource = "http://www.inf.fu-berlin.de/inst/ag-nbi/lehre/0405/V_NP/geheim5/geheim.txt";
// Namen / Passworte für die Login-Versuche
final String[] nameDict = {"Alle", "Keiner", "Jeder"};
final String[] passDict = {"gelb", "blau", "rot"};
// Ein BASE64-Encoder zur Übermittlung des Logins
BASE64Encoder encoder = new BASE64Encoder();
public AuthCheck() throws IOException {
// Verbindung herstellen
System.out.println("Verbinde zu "+resource);
URL page = new URL(resource);
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
conn.connect();
// prüfen, ob Authentifizierung verlangt wird
if (conn.getResponseCode() == 401) {
System.out.println("Realm: "+conn.getHeaderField("WWW-Authenticate")+"\n");
// sämtliche Name-Passwort-Kombinationen durchprobieren
for (int i = 0;i < nameDict.length; i++) {
for (int j = 0; j < passDict.length; j++) {
System.out.print("Login mit "+nameDict[i]+":"+passDict[j]+"... ");
// Login-Daten für die Übermittlung codieren
String login = encoder.encode((nameDict[i] + ":" + passDict[j]).getBytes());
// Authentifizierung per "Basic Authentication Scheme"
conn = (HttpURLConnection) page.openConnection();
conn.setRequestProperty("Authorization", "Basic "+login);
conn.connect();
// Login erfolgreich?
if (conn.getResponseCode() == 200) {
System.out.println("erfolgreich!");
}
else {
System.out.println("fehlgeschlagen");
}
}
}
}
else {
System.out.println("The resource is not available via 'Basic Authentication Scheme' ("+conn.getResponseCode()+").");
}
}
public static void main(String[] args) throws IOException {
new AuthCheck();
}
}
@@ -0,0 +1,162 @@
//Gruppe 01 (Übung 2)
//Aufgabe 2-1
package uebung02.aufgabe01;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
/**
* Vergleicht zwei Ressourcen im Netz auf Übereinstimmung.
* Zunächst werden die Inhalts-Header, danach die Ressourcen
* selbst verglichen.
*
* @author Tilman Walther
*/
public class NetComparator {
// Header, die auf Unterschiede im Inhalt schließen lassen
private static String[] header = new String[] {
"Content-Type",
"Content-Length",
"Content-Encoding",
"Content-Language",
"Last-Modified",
"Expires" };
/**
* Compares two resources given as URLs.
*
* @param s1 The URL for the first resource
* @param s2 The URL for the second resource
* @return true, if the resources are equal, false otherwise
* @throws IOException if an I/O Error occurs
*/
public static boolean compare(String s1, String s2) throws IOException {
// Verbindungen für die Ressourcen erstellen
URL url1 = new URL(s1);
URLConnection connection1 = url1.openConnection();
URL url2 = new URL(s2);
URLConnection connection2 = url2.openConnection();
// Header vergleichen
String val1; // Header-Value Resource 1
String val2; // Header-Value Resource 2
long differences = 0; // Anz. festegestellter Unterschiede
// relevante Header durchgehen
for (int i = 0; i < header.length; i++) {
val1 = connection1.getHeaderField(header[i]);
val2 = connection2.getHeaderField(header[i]);
if ((val1 != null) && (val2 != null)) {
if (!val1.equals(val2)) {
System.out.println("Header verschieden: "+header[i]+" "+val1+" / "+val2);
differences++;
}
}
}
// Inhalt vergleichen
BufferedInputStream input1 = new BufferedInputStream(connection1.getInputStream());
BufferedInputStream input2 = new BufferedInputStream(connection2.getInputStream());
long lengthRead = 0;
long bytesDifferent = 0;
long areasDifferent = 0;
int length1 = 0;
int length2 = 0;
byte[] buffer1 = new byte[1024];
byte[] buffer2 = new byte[1024];
boolean differentArea = false;
long marker = 0;
// Inhalt vergleichen
do {
length1 = input1.read(buffer1);
length2 = input2.read(buffer2);
int in1 = Math.min(length1, length2);
// Unterschiedliche Bereiche suchen
for (int i = 0; i < in1; i++) {
if ((buffer1[i] != buffer2[i])) {
if (!differentArea) {
differentArea = true;
marker = lengthRead+i;
}
}
else if (differentArea) {
differentArea = false;
bytesDifferent += (lengthRead + i - marker);
System.out.println("Bereich von "+marker+" bis "+(lengthRead + i-1)+" unterschiedlich");
areasDifferent++;
differences++;
}
}
lengthRead += length1;
} while ((length1 > 0) && (length1 == length2));
// Überprüfen, ob aus beiden Streams gleich viel gelesen wurde, bzw.
// ob ein Stream noch nicht am Ende angelangt ist
long diffLength = Math.abs(input1.available()+length1-input2.available()-length2);
if (diffLength > 0) {
System.out.println("Länge unterschiedlich ("+diffLength+" Byte)");
differences++;
}
// Endergebnis ausgeben
if (differences > 0) {
System.out.println("Test beendet, "+differences+" Unterschiede festgestellt.\nDer Inhalt unterscheidet sich in "+bytesDifferent+" Bytes in "+areasDifferent+" Bereichen.");
return false;
}
System.out.println("Test beendet, Ressourcen stimmen überein.");
return true;
}
public static void main(String[] args) throws IOException {
if (args.length == 2) {
NetComparator.compare(args[0], args[1]);
}
else if (args.length == 0) {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Please insert first URL: ");
String s1 = in.readLine();
System.out.print("Please insert second URL: ");
String s2 = in.readLine();
NetComparator.compare(s1, s2);
}
else {
System.out.println("Aufruf: NetCompare [url1 url2]");
}
}
}
@@ -0,0 +1,304 @@
// Netzprogrammierung
// Gruppe 01 (Übung 1)
// Aufgabe 1-4
/*
ProxyServer.java
Anmerkungen:
- Dem Proxyserver können auf der Kommandozeile optional Port und Debug Level als int-Werte
übergeben werden (Silent Mode, nur Header, etc.). Als default werden Port 10000 und Debug
Level 3 genutzt.
Konzepte:
- Die Eingabeströme von Client und v.a. Server werden über binäre Inputstreams abgewickelt,
um Bilder und andere Binärdaten zu erhalten
- Aus dem Client-Request werden Server und Port geparst, so kann bspw. auch http über Port
8080 abgefragt werden
- Der vom Client entgegengenommene Header wird teilweise bereinigt, da er sich an einen
Proxy richtet (Zeile 148 ff.)
- Die Antwort vom Server wird über die private Methode readLine() (Z. 242 ff.) abgewickelt, so
kann der InputStream komfortabel gehandhabt werden
- Die empfangenen Headerzeilen werden aufsummiert und durch die angeforderten Ressourcen
geteilt. Das Ergebnis wird über den Header an den Client gesendet (Z. 190 ff.)
- Die meisten Exceptions werden nur abgefangen, der Proxyserver läuft danach wieder an, da
die meisten Fehler durch Abbruch der Verbindung durch den Client u.ä. entstehen, bemerkt
man dies im Betrieb i.d.R. nicht
- Die einzige gesondert behandelte Exception ist die Connection Exception (Z. 214): Tritt sie
auf, wird HTTP-Fehlercode 500 an den Client übermittelt
*/
package uebung01.aufgabe04;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.ConnectException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.util.Iterator;
import java.util.LinkedList;
/**
* Ein einfacher Proxy-Server, der die durchschnittliche Anzahl empfangener Headerzeilen ermittelt.
*
* @author Tilman Walther
*/
public class ProxyServer {
// da unser einfacher Proxy die content-length nicht beruecksichtigt (die
// auch nicht von jedem Server gesendet wird), muessen Verbindungen oft
// per Timeout beendet werden.
final int SERVER_TIMEOUT = 2500;
// da Java den Linefeed dem System anpasst, nutzen wir einen
// String, der sich nach dem HTTP-Protokoll richtet
final String LF = new String(""+((char) 13)+((char) 10));
long headerLineCount = 0;
long itemCount = 0;
StringBuffer lineBuffer = new StringBuffer(600);
public ProxyServer(int port, int message) throws IOException {
System.out.println("PROXY: Starting ProxyServer on port "+port);
ServerSocket proxySocket = new ServerSocket(port);
Socket client;
BufferedInputStream clientIn;
PrintStream clientOut;
Socket server;
BufferedInputStream serverIn;
PrintStream serverOut;
String request;
String domain;
int serverport;
LinkedList requestStrings = new LinkedList();
String s;
byte[] buffer = new byte[1024];
int in1;
long headerLineAverage;
while (true) {
if (message > 1) System.out.println("PROXY: Listening... (press Ctrl+C to end)");
client = proxySocket.accept();
clientIn = new BufferedInputStream(client.getInputStream());
clientOut = new PrintStream(client.getOutputStream(), true);
try {
// Anfrage vom Browser holen
s = readLine(clientIn);
// Ressource extrahieren
request = s.substring(0, s.indexOf(" ")+1) + s.substring(s.indexOf("/", s.indexOf("//")+2));
// Domain und Port extrahieren
domain = s.substring(s.indexOf("//")+2);
domain = domain.substring(0, domain.indexOf("/"));
if ((in1 = domain.indexOf((int) ':')) > -1 ) {
serverport = Integer.parseInt(domain.substring(in1+1));
domain = domain.substring(0, in1);
}
else {
serverport = 80;
}
if (message > 1) System.out.print("PROXY: Request from client: "+s);
// Restlichen Anfrage-Header holen
requestStrings.clear();
do {
s = readLine(clientIn);
requestStrings.add(s);
if (message > 4) System.out.print(" "+s);
} while (!s.equals(LF));
long time = System.currentTimeMillis();
try {
if (message > 1) System.out.println("PROXY: Connecting server "+domain+":"+serverport);
server = new Socket(domain, serverport);
server.setSoTimeout(SERVER_TIMEOUT);
serverIn = new BufferedInputStream(server.getInputStream());
serverOut = new PrintStream(server.getOutputStream(), true);
if (message > 1) System.out.print("PROXY: Sending request to server: "+request);
serverOut.print(request);
// Angepassten Header an Server schicken
Iterator iter = requestStrings.iterator();
while (iter.hasNext()) {
s = (String) iter.next();
if (s.startsWith("Proxy-Connection")) {
serverOut.print("Connection: close"+LF);
if (message > 2) System.out.print(" Connection: close"+LF);
}
else if (s.startsWith("Transfer-Encoding")) {
serverOut.print("Transfer-Encoding: identity"+LF);
if (message > 2) System.out.print(" Transfer-Encoding: identity"+LF);
}
else if (s.startsWith("Accept-Encoding")) {
s = s.substring(0,(s.length()-2)).concat(",identity"+LF);
//s = "Accept-Encoding: identity"+LF;
serverOut.print(s);
if (message > 2) System.out.print(" "+s);
}
else {
serverOut.print(s);
if (message > 2) System.out.print(" "+s);
}
}
// Antwort vom Server entgegennehmen
try {
// Header empfangen
s = readLine(serverIn);
// --> Hier koennen HTTP response codes abgefangen werden
if (message > 1) System.out.print("PROXY: Receiving data from server: "+s);
itemCount++;
while (!s.equals(LF)) {
headerLineCount++;
if (message > 2) System.out.print(" "+s);
clientOut.print(s);
s = readLine(serverIn);
}
// durchschnittliche Anzahl der Headerzeilen berechnen
headerLineAverage = headerLineCount / itemCount;
if (message > 2) System.out.print(" X-mean-headercount: "+ headerLineAverage + LF + LF);
clientOut.print("X-mean-headercount: "+ headerLineAverage + LF + LF);
// Daten empfangen
while ((in1 = serverIn.read(buffer)) > 0) {
if (message > 3) System.out.write(buffer, 0, in1);
clientOut.write(buffer, 0, in1);
}
}
catch (SocketTimeoutException ste) {
if (message > 1) System.err.println("PROXY: Connection timed out");
}
if (message > 1) System.out.println("PROXY: Time "+(System.currentTimeMillis()-time)+" ms");
if (message > 1) System.out.println("PROXY: Unconnect...\n");
serverIn.close();
serverOut.close();
server.close();
}
catch (ConnectException ce) {
if (message > 0) System.err.println("ConnectException, sending code 500 to client");
buffer = ("HTTP/1.0 500\nContent Type: text/plain\n\nError while connecting server: "+domain+"\n").getBytes();
clientOut.write(buffer, 0, ("HTTP/1.0 500\nContent Type: text/plain\n\nError while connecting server: "+domain+"\n").length());
}
clientIn.close();
clientOut.close();
client.close();
}
catch (SocketException se) {
if (message > 4) System.err.println("SocketException");
}
catch (Exception e) {
// nothing, just try again
if (message > 4) e.printStackTrace();
}
}
//proxySocket.close();
}
/**
* Liest eine Zeile vom binären Eingabestrom.
* (Auf diese Weise bleiben binäre Daten korrekt erhalten.)
*/
private String readLine(InputStream in) throws IOException
{
int i;
lineBuffer.setLength(0);
while (((i = in.read()) > 0) && (i != 13)){
lineBuffer.append((char) i);
}
// nach HTTP 1.1 müssten die Zeilenenden mit #13#10 markiert sein
// (durch die Aufteilung schlucken wir auch Unix/Macintosh)
if (i == 13) {
lineBuffer.append((char) 13);
in.mark(1);
if (in.read() != 10)
in.reset();
else
lineBuffer.append((char) 10);
}
return lineBuffer.toString();
}
public static void main(String[] args) throws IOException {
int port = 10000; // default port
int message = 3; // default output level
if (args.length > 2) {
System.out.println("usage: MultServer [port number] [output level]");
}
else {
if (args.length > 0) {
try {
port = Integer.parseInt(args[0]);
}
catch (NumberFormatException nfe) {
System.out.println(args[0]+" is not a valid port number.\nusage: MultServer [port number] [output level]");
System.exit(1);
}
}
if (args.length > 1) {
try {
port = Integer.parseInt(args[1]);
}
catch (NumberFormatException nfe) {
System.out.println(args[0]+" is not a valid port number.\nusage: MultServer [port number] [output level]");
System.exit(1);
}
}
}
new ProxyServer(port, message);
}
}
@@ -0,0 +1,264 @@
//Gruppe 01 (Übung 4)
//Aufgabe 4-3
package uebung04.aufgabe03;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.HTML;
import javax.swing.text.html.HTML.Tag;
import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.html.parser.ParserDelegator;
/**
* Sucht in einer HTML-Ressource nach eingebetten Objekten und summiert die Dateigrößen auf,
* wobei mehrfach verlinkte Objekte nur einmal gezählt werden.
* Bei Framesets werden sämtliche Frames ausgewertet, in mehreren Frames dargestellte Seiten
* werden nur einfach gezählt.
*
* @author Tilman Walther
* @version 2.1
*/
public class SiteSize extends ParserCallback {
private URL url; // die URL der HTML-Ressource
private URLConnection connection; // Verbindung zur HTML-Ressource
private HashSet objects = null; // speichert URLs der bereits gezählten Objekten
private long size = 0; // die Größe aller gezählten Objekte
private ParserDelegator parser = new ParserDelegator(); // parst die Ressource und ruft handleSimpleTag() auf
/**
* Parses the resource behind the given URL and measures the size.
* If the URL points to a non-HTML resource the size will be zero.
* @param url the URL for the resource to parse
* @return the size of the website including all embedded objects
* @throws IOException if an I/O error occurs
*/
public long getSize(URL url) throws IOException {
/* Für Testzwecke: Durchleitungsproxy einstellen /
java.util.Properties props = System.getProperties();
props.put("proxySet", "true");
props.put("proxyHost", "127.0.0.1");
props.put("proxyPort", "10000");
/* --------------------------------------------- */
System.out.println("\nparsing "+url);
this.url = url;
connection = url.openConnection();
// Daten vom Server im "identity"-Format anfordern
connection.addRequestProperty("Accept-Encoding", "identity");
// TODO für Testzwecke:
//connection.addRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/125.5.6 (KHTML, like Gecko) Safari/125.12");
connection.connect();
//System.out.println("Transfer-Encoding: "+connection.getHeaderField("transfer-encoding")+"\n");
// falls objects nicht bereits durch den privaten Konstruktor
// inititalisiert wurde, neues HashSet erzeugen
if (objects == null) objects = new HashSet();
// auf HTML-Inhalt prüfen
if (connection.getContentType().startsWith("text/html")) {
// Größe der Seite zur Gesamtgröße addieren
addSize(url);
// eingebettete Objekte mit Parser finden/addieren
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
parser.parse(br, this, true);
}
// Gesamtgröße zurückgeben
return size;
}
/**
* This private method is used for recursive processing of framesets.
* In order not to count linked objects twice, the HashSet 'objects' is passed.
* @param url the URL for the actual frame
* @param objects the HashSet containing all objects that have already been counted
* @return the size if the subframe
* @throws IOException if an I/O error occurs
*/
private long getSize(URL url, HashSet objects) throws IOException {
this.objects = objects;
return getSize(url);
}
/**
* Overrides javax.swing.text.html.HTMLEditorKit.ParserCallback.handleSimpleTag() which is called by the ParserDelegator
* @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleSimpleTag(javax.swing.text.html.HTML.Tag, javax.swing.text.MutableAttributeSet, int)
*/
public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) {
String objLink = null;
try {
if (t == HTML.Tag.FRAME) {
// leider trifft man öfter auf dummy-frames (Dreamweaver!), deswegen
// fehlt ab und zu die Quelle
if (a.getAttribute(HTML.Attribute.SRC) != null) {
// absuluten Pfad zur Ressource nachvollziehen, um mehrfache Zählung zu vermeiden
URL frameUrl = generateURL(a.getAttribute(HTML.Attribute.SRC).toString());
// Frame von neuem SiteSize-Objekt parsen lassen
SiteSize frameSize = new SiteSize();
size += frameSize.getSize(frameUrl, objects);
}
} else {
if (t == HTML.Tag.APPLET) {
// Applets können direkt via CODE-Attribut oder als Archiv verlinkt sein
if (a.getAttribute(HTML.Attribute.ARCHIVE) != null) {
objLink = a.getAttribute(HTML.Attribute.ARCHIVE).toString();
} else {
objLink = a.getAttribute(HTML.Attribute.CODE).toString();
}
} else if (t == HTML.Tag.IMG) {
objLink = a.getAttribute(HTML.Attribute.SRC).toString();
} else if (t == HTML.Tag.OBJECT) {
objLink = a.getAttribute(HTML.Attribute.DATA).toString();
} else if (t == HTML.Tag.LINK) {
objLink = a.getAttribute(HTML.Attribute.HREF).toString();
}
if (objLink != null) {
try {
// absuluten Pfad zur Ressource nachvollziehen, um mehrfache Zählung zu vermeiden
addSize(generateURL(objLink));
} catch (MalformedURLException mue) {
System.out.println("MalformedURLException on position " + pos + ": '" + objLink + "'");
}
}
}
} catch (IOException ioe) {
System.out.println("IOException (" + pos + "): Could not connect to linked object. ("+objLink+")");
}
}
/**
* Overrides javax.swing.text.html.HTMLEditorKit.ParserCallback.handleStartTag() which is called by the ParserDelegator.
* @see javax.swing.text.html.HTMLEditorKit.ParserCallback#handleStartTag(javax.swing.text.html.HTML.Tag, javax.swing.text.MutableAttributeSet, int)
*/
public void handleStartTag(Tag t, MutableAttributeSet a, int pos) {
// Da APPLET- und OBJECT-Tags auch als StartTags vorkommen können, wird das der Aufruf
// in diesem Fall an handleSimpleTag() weitergegeben
if ((t == HTML.Tag.APPLET) || (t == HTML.Tag.OBJECT)) handleSimpleTag(t, a, pos);
}
/**
* Adds the size of the resource that the given URLConnection points to if it has not already been counted
* @param connection an URLConnection to a resource
* @throws IOException if an I/O error occurs
*/
private void addSize(URL url) throws IOException {
URLConnection resConn = url.openConnection();
// TODO für Testzwecke:
//resConn.addRequestProperty("User-Agent", "Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; de-DE; rv:1.7) Gecko/20040803 Firefox/0.9.3");
resConn.connect();
String resUrlStr = url.toString();
if (!objects.contains(resUrlStr)) {
objects.add(resUrlStr);
int resLength = resConn.getContentLength();
if (resLength >= 0) {
size += resLength;
}
else {
// da der Content-Length Header nicht übermittelt wurde, muss zur
// Messung die Ressource übertragen werden
int bytesRead;
byte[] buffer = new byte[1024];
BufferedInputStream input = new BufferedInputStream(resConn.getInputStream());
resLength = 0;
while ((bytesRead = input.read(buffer)) >= 0) {
resLength += bytesRead;
}
size += resLength;
}
System.out.println("added '" + resUrlStr + "' (" + resLength + " bytes)");
}
}
/**
* Generates the URL for a (relative) link extracted from a tag attribute
* @param link a resource link from a tag attribute
* @return the URL to the resource
* @throws MalformedURLException
*/
// TODO wahrscheinlich lässt sich diese Methode (zumindest teilw.) durch URI.relativize() ersetzen
private URL generateURL(String link) throws MalformedURLException {
if (link.startsWith("//")) link = "http:" + link;
String resUrlStr = null;
if (link.indexOf("://") > 0) {
resUrlStr = new String(link);
} else if (link.startsWith("/")) {
resUrlStr = new String(url.getProtocol() + "://" + url.getAuthority() + link);
} else {
String path = url.getPath();
if (path.length() > 0) path = path.substring(0, path.lastIndexOf("/"));
resUrlStr= new String(url.getProtocol() + "://" + url.getAuthority() + path + "/" + link);
}
int i, j;
while ( ((i = resUrlStr.indexOf("../")) > -1) && ((j = resUrlStr.indexOf("/", i+3)) > -1) ){
resUrlStr = resUrlStr.substring(0,i) + resUrlStr.substring(j+1);
}
//new URL(URLEncoder.encode(resUrlStr, "UTF-8"));
return new URL(resUrlStr);
}
public static void main(String[] args) {
try {
String urlString;
if (args.length == 0) {
// URL von der Kommandozeile lesen
BufferedReader din = new BufferedReader(new InputStreamReader(System.in));
System.out.print("URL: ");
urlString = din.readLine();
} else {
urlString = args[0];
}
// URL erzeugen
URL url = new URL(urlString);
// SiteSize-Objekt erzeugen
SiteSize siteSize = new SiteSize();
// Brutto-Größe messen und ausgeben
System.out.println("\nSize of content: " + siteSize.getSize(url) + " bytes");
} catch (Exception e) {
e.printStackTrace();
}
}
}