Struktura archiwum komunikatora Tlen.pl
Tlen.pl tworzy dla każdego profilu folder DataBase, umiejscowiony w katalogu danego profilu. W folderze tym są przechowywane pliki archiwum, a w nich zależnie od ustawień - wiadomości, rozmowy i smsy.
Pliki archiwum można podzielić na dwa rodzaje - pliki indeksowe i pliki danych.
Pliki indeksowe, o rozszerzeniu .idx, jak sama nazwa wskazuje, składają się z indeksów przechowujących zapisane informacje o wiadomościach, rozmowach, i smsach, których treść znajduje się w plikach danych, identyfikowanych rozszerzeniem .dat.
W niniejszej publikacji postaram się omówić budowę archiwum.
Wszystkie wartości liczbowe zapisane są w formie Little-Endian, czyli zgodnie z kolejnością bajtów maszyn Intela.
Przy opisie struktur, założono, że wyrównanie do granicy rozmiaru słowa wynosi 1 bajt. Przez co należy wyłączyć w kompilatorze domyślnie włączone wyrównanie zmiennych do rozmiaru słowa danej architektury. Należy zwrócić uwagę na rozmiar typów zmiennych i kolejność bajtów.
Myślę, że nie ma potrzeby opisywania przeznaczenia poszczególnych pól zawartych w przedstawianych strukturach, ich nazwy i zawarte komentarze "mówią" same za siebie.
Pola o nieznanym lub nie do końca jasnym znaczeniu, oznaczono przedrostkiem unknown.
Jako, iż tlen.pl tworzony jest z wykorzystaniem VCLa, wszelkie dane na temat daty i czasu zostały zapisane w Borlandowskim formacie TDateTime. Informacje o prostej konwersji na bardziej ludzki format – uniksowy znacznik czasu można znależć tutaj: Convert TDateTime to Unix TimeStamp.
Wszelkie wartości offset, występujące w strukturach są liczone względem początku pliku.
Rozmowy
Rozmowy archiwizowane są w plikach chats.idx i chats.dat.
Plik indeksu zawiera listę wszystkich przeprowadzonych rozmów. Lista składa się z rekordów, które przechowują informacje o rozmowie, każdy rekord reprezentowany jest przez strukturę:
struct IDXchat {
char name[26]; // nazwa rozmowcy
char network[6]; // nazwa sieci (nieobsługiwane)
double time; // czas w TDateTime
int flags; // flagi
int offset; // pozycja pierwszej wypowiedzi
int count; // ilosc wypowiedzi
int ID; // ID rozmowy
};
Rozmiar tej struktury wynosi 56 bajtów.
Plik danych - chats.dat składa się z rekordów tworzących listę, gdzie każdy rekord reprezentuje jedną wypowiedz z rozmowy. Każda wypowiedz zapisana jest w formie struktury:
struct DATchat {
double time; // czas wypowiedzi w TDateTime
int flags; // flagi
int size; // rozmiar wypowiedzi
int ID; // ID rozmowy
int unknown;
char msg[]; // tresc wypowiedzi
};
Struktura ta ma rozmiar równy 24 bajty + size.
Flagi w powyższych strukturach opisują dodatkowe właściwości. Obecnie dla każdej po jednej:
#define ARCHIVE_CHAT_FLAG_SELECT 0x00001 // IDXchat / zaznaczona do usuniecia
#define ARCHIVE_CHAT_FLAG_SEND 0x00001 // DATchat / wyslana przez nas
Wzajemna relacja miedzy indeksem rozmowy a jej wypowiedziami identyfikowana jest na podstawie ID. Przy czym wypowiedzi danej rozmowy nie są zapisane w jednym ciągu kolejnych po sobie rekordów, a "rozrzucone" po całym pliku.
Wiadomości
Wiadomości przechowywane są w plikach msgs.idx i msgs.dat.
Plik indeksowy wiadomości, podobnie jak w przypadku rozmów, jest listą wszystkich odebranych i wysłanych wiadomości. Każda rozmowa zapisana jest w postaci poniższej, 56-bajtowej struktury:
struct IDXmsg {
char name[26]; // nazwa nadawcy
char network[6]; // nazwa sieci (nieobsługiwane)
double time; // czas wiadomosci w TDateTime
int flags; // flagi
int offset; // pozycja wiadomosci
int size; // rozmiar wiadomosci
int unknown;
};
Flagi opisują dodatkowe właściwości wiadomości. Obecnie istnieją tylko dwie:
#define ARCHIVE_MSG_FLAG_SEND 0x00001 // wyslana przez nas
#define ARCHIVE_MSG_FLAG_SELECT 0x10000 // zaznaczona do usuniecia
Plik danych jest zwykłym plikiem tekstowym zawierającym treści wszystkich wiadomości oddzielonych od siebie spacją. Na podstawie danych zawartych w strukturach IDXmsg - offset i size można w łatwy sposób przypisać daną treść do konkretnej struktury wiadomości, odwzorowując tym samym pełną, właściwą wiadomość.
SMSy
Historia wysłanych wiadomości smsowych zawarta jest w dwóch plikach - sms.idx i sms.dat. Ich budowa jest zbliżona do budowy plików przechowywujących archiwum wiadomości.
Tak, jak pozostałe pliki indeksowe archiwum tlena, również sms.idx zawiera informacje dotyczące wszystkich wysłanych smsach w postaci listy odpowiednich struktur o rozmiarze 40 bajtów. Struktury te mają następującą budowę:
struct IDXsms {
char tel[12]; // nr telefonu
int unknown1;
double time; // czas wyslania w TDateTime
int flags; // flagi
int offset; // pozycja wiadomosci
short size; // rozmiar wiadomosci
short recv; // odebrany sms
int unknown2;
};
Flagi opisują dodatkowe właściwości smsa:
#define ARCHIVE_SMS_FLAG_SELECT 0x00001 // zaznaczony do usuniecia
Plik danych sms.dat zawierający treści poszczególnych wiadomości sms, jest, tak jak w przypadku msgs.dat, zwykłym plikiem tekstowy. Treści oddzielone są spacją, a dostęp do nich i identyfikacja następuje na podstawie danych zawartych w indeksach.
Przy usuwaniu rozmów, wiadomości czy smsów z archiwum, tlen od razu nie usuwa fizycznie danych z plików archiwum. Specjalnie oznacza usuniete rekordy w plikach indeksowych, co by nie były brane pod uwagę przy wyświetlaniu. Fizyczne usuniecie następuje dopiero w czasie wykonywania kompaktowania archiwum.
Istnieje, więc możliwość odzyskania treści usuniętych wiadomości i smsów, a w przypadku rozmów teoretycznie jest możliwość pełnego odtworzenia rozmowy.
Oznaczenie usuniętych rekordów jest rozpoznawane po wartości pól time i size, time zostaje wyzerowane, a wartość size ustawiona na -1, pozostałe pola zawierają niezidentyfikowane dane.
Nie należy tutaj mylić "usuniętych" z polem select, które słuzy do czegoś zupełnie innego - informuje ono o "zaznaczeniu do usunięcia" danej pozycji w archiwum tlena.
To byłoby wszystko na temat struktury archiwum tlena.
W wolnym czasie postaram się napisać i udostępnić kilka przykładowych programów operujących na plikach archiwum.
Obecnie tylko jeden "ciekawszy" program, na jaki trafiłem całkiem przypadkiem, można znaleźć na forum ekipa.tlen.pl w temacie Dostep do archiwum tlena. Niestety napisany w Delphi :(.