Inital commit
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user