25 kwietnia 2009

NNTP, Apache Commons Net i polskie znaki w wiadomościach

Jak co weekend, dzisiaj też usiadłem do magisterki. Spośród kilku rzeczy, które sobie zaplanowałem pojawił się temat wysyłania wiadomości/powiadomień na wewnętrzną grupę dyskusyjną mojego akademika za pomocą protokołu NNTP.

Szybkie rozpoznanie pokazało, że całość jest prosta jak przysłowiowa budowa cepa i nie powinna sprawiać żadnych problemów. Poniżej mała klasa pokazująca sposób wysyłania posta na grupę pw.test przy pomocy biblioteki Apache Commons Net.


package pl.tdziurko.nntptest.main;

import java.io.Writer;
import org.apache.commons.net.nntp.NNTPClient;
import org.apache.commons.net.nntp.SimpleNNTPHeader;

/**
*
* @author Tomasz Dziurko
*/
public class Main {

public static void main(String[] args) throws Exception {

NNTPClient client = new NNTPClient();
client.connect("news.ustronie.pw.edu.pl");

client.selectNewsgroup("pw.test");
Writer postArticle = client.postArticle();

SimpleNNTPHeader headers =
new SimpleNNTPHeader("Tomasz Dziurko <tdziurko@gmail.com>", "Test kodowania polskich znaków");
headers.addNewsgroup("pw.test");
headers.addHeaderField("Mime-Version", "1.0");
headers.addHeaderField("Content-Type","text/plain; charset=UTF-8");
headers.addHeaderField("Content-Transfer-Encoding", "8bit");

postArticle.write(headers.toString());
postArticle.write("ąęóśłżźćń - test polskich znaków\r\n");
postArticle.close();

client.completePendingCommand();

client.disconnect();
}

}


Wszystko działało zgodnie z oczekiwaniami do momentu, gdy zacząłem w treści wiadomości używać polskich znaków. Zamiast "ąęóśłżźćń" pojawił się następujący obrazek:


Kombinacje z ustawianiem innego kodowania w nagłówku wysyłanej wiadomości, zmiana kodowania całego projektu czy nawet zmiana ustawień czytnika (tak tak, zacząłem winić nawet biednego Thunderbirda ;) ) nic nie pomogły. Wtedy postanowiłem zajrzeć do źródeł biblioteki ze stajni Apache'a i po krótkim śledztwie znalazłem winowajcę: klasę org.apache.commons.net.nntp.NNTP.


public class NNTP extends SocketClient
{
/*** The default NNTP port. Its value is 119 according to RFC 977. ***/
public static final int DEFAULT_PORT = 119;

// We have to ensure that the protocol communication is in ASCII
// but we use ISO-8859-1 just in case 8-bit characters cross
// the wire.

private static final String __DEFAULT_ENCODING = "ISO-8859-1";

...

/***
* Initiates control connections and gets initial reply, determining
* if the client is allowed to post to the server. Initializes
* {@link #_reader_} and {@link #_writer_} to wrap
* {@link SocketClient#_input_} and {@link SocketClient#_output_}.
***/
@Override
protected void _connectAction_() throws IOException
{
super._connectAction_();
_reader_ =
new BufferedReader(new InputStreamReader(_input_,
__DEFAULT_ENCODING));
_writer_ =
new BufferedWriter(new OutputStreamWriter(_output_,
__DEFAULT_ENCODING));
__getReply();

_isAllowedToPost = (_replyCode == NNTPReply.SERVER_READY_POSTING_ALLOWED);
}

...

}

Jak widać przy tworzeniu zarówno Writera i Readera zastosowano kodowanie ISO-8859-1, czyli nie posiadające w swoich zasobach polskich ogonków. Gdy zaczynałem się zastanawiać w jaki sposób zbuduję całą bibliotekę po zmianie wartości zmiennej __DEFAULT_ENCODING na "UTF-8", zauważyłem w archiwum ze źródłami plik pom.xml. Alleluja! - pomyślałem - Maven lekiem na moje problemy. Teraz wszystko powinno pójść niczym z płatka :)

NetBeans 6.5 z zainstalowanym pluginem pozwala na otwieranie projektów z pliku pom.xml, więc już w IDE mogłem dokonać modyfikacji biblioteki. Następnie uruchomiłem testy i ku mojemu zdziwieniu okazało się, że jeden z nich nie zakończył się sukcesem. Szybkie pytanie do Wielkiego Googla i już wiedziałem, że pewna metoda testująca działa bez problemów tylko na anglojęzycznych systemach operacyjnych (przenośność Javy ;) ). Żeby już nie przedłużać zabawy ze źródłami po prostu ją wykomentowałem i uruchomiłem testy ponownie.


Ufff, udało się :) Teraz mogłem zbudować zmodyfikowaną bibliotekę i podczepić ją do mojego projektu wysyłającego wiadomość testową.
Poniżej można zobaczyć efekty, wszystkie polskie znaki są prawidłowo wysyłane na grupę dyskusyjną.

Brak komentarzy:

Prześlij komentarz