Sieci komputerowe zadanie

Zadanie zaliczeniowe z Sieci Komputerowych

Oto treść:

Zadanie zaliczeniowe z Laboratorium z Sieci Komputerowych 2007

Należy napisać program filtrujacy strumień pakietów wywoływany z pięcioma argumentami:
- nazwš wej?ciowego pliku zawierajšcego pakiety (zrzut tcpdump),
- nazwš pliku wyj?ciowego, do którego należy zapisać wszystkie przepuszczone pakiety,
- nazwš pliku wyj?ciowego z informacjami na temat przepuszczanych i odrzuconych pakietów,
- nazwš pliku z "czarnš" listš adresów ip,
- nazwš pliku z "białš" listš adresów ip i portów TCP,
    nazwa_programu plik_in plik_out plik_admin plik_bad plik_good

Plik plik_bad ma następujšcy format. W kolejnych linijkach umieszczone sš:
    adres_ip niepusty_cišg_białych_znaków kierunek
gdzie kierunek jest jednym ze słów SRC lub DEST okre?lajšcymi czy chodzi o ?ródłowy czy docelowy adres ip.

Plik plik_good ma następujšcy format. W kolejnych linijkach umieszczone sš:
    adres_ip niepusty_cišg_białych_znaków kierunek niepusty_cišg_białych_znaków port_begin,port_end
gdzie:
    - kierunek jest jednym ze słów SRC lub DEST okre?lajšcymi czy chodzi o ?ródłowy czy docelowy adres ip,
    - port_begin,port_end oznaczajš zakres portów (okre?lony tylko dla protokołów TCP i UDP)
    ?ródłowych lub docelowych (w zależno?ci od parametru kierunek).

Każdy pakiet należy poddać analizie. Pakiet odrzucamy jeżeli spełniony jest przynajmniej jeden z warunków:
1) ?ródłowy lub docelowy adres ip znajduje się w plik_bad i zgadza się kierunek przesyłu danych,
2) pakiet jest wysyłany za pomocš protokołu TCP lub UDP i jego ?ródłowy lub docelowy adres ip
    znajduje się w plik_good, ale numer portu nie należy do podanego zakresu,
3) pakiet jest wysyłany za pomocš protokołu TCP, ale nie dane w nim zawarte nie pasujš do następujšcego formatu:
    pierwszym znakiem jest cyfra od 1 do 9 mówišca ile razy powinny być w danym pakiecie powtórzone dane,
    na przykład:
        2_tresc_tresc
        3_tresc_tresc_tresc
        7_tresc_tresc_tresc_tresc_tresc_tresc_tresc
W przypadku odrzucenia pakietu należy wpisać nowš linię do plik_admin w następujšcym formacie:
    ip_nadawcy ip_odbiorcy nazwa_protokołu komunikat
przy czym komunikat jest jednym spo?ród:
    - BAD SRC/DEST IP
        w przypadku niespełnienia warunku 1,
    - BAD SRC/DEST PORT
        w przypadku niespełnienia warunku 2,
    - BAD PACKET FORMAT, MISSING NUMBER
      BAD PACKET FORMAT, NOT MATCHING DATA
        w przypadku niespełnienia warunku 3 z powodu odpowiednio braku cyfry na poczštku lub braku pasujšcych danych.

Pozostałe pakiety należy przepu?cić wpisujšc do plik_out oraz wpisać nowš linię do plik_admin w następujšcym formacie:
    ip_nadawcy ip_odbiorcy nazwa_protokołu PACKET OK

Program należy przesłać na adres mailowy prowadzšcego grupę ćwiczeniowš:
    piotr.sawicki@mimuw.edu.pl
    michal.bernardelli@mimuw.edu.pl
do 2 grudnia 2007 roku do godziny 23:59.
Ocena rozwišzań wysłanych po tym terminie (wliczajšc w to sesję poprawkowš) będzie obniżona o jeden stopień.
Program powinien być skompresowany wraz z zaprojektowanym przez siebie kompletem testów.
Nazwa spakowanego pliku powinna być taka sama jak wydziałowy login.
Program ma się kompilować i działać na komputerach w laboratorium komputerowym MIM.
Za brak lub niewystarczajšcš liczbę komentarzy w kodzie ?ródłowym programu będzie obniżana ocena.
Na ostatnich ćwiczeniach należy przyj?ć i zaprezentować działanie swojego programu.

A oto rozwiazanie:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 



/* default snap length (maximum bytes per packet to capture) */
#define SNAP_LEN 1518

/* ethernet headers are always exactly 14 bytes [1] */
#define SIZE_ETHERNET 14

/* Ethernet addresses are 6 bytes */
#define ETHER_ADDR_LEN	6

pcap_dumper_t *plik;

/* Ethernet header */

struct sniff_ethernet {
        u_char  ether_dhost[ETHER_ADDR_LEN];    /* destination host address */
        u_char  ether_shost[ETHER_ADDR_LEN];    /* source host address */
        u_short ether_type;                     /* IP? ARP? RARP? etc */
};

/* IP header */
struct sniff_ip {
        u_char  ip_vhl;                 /* version <> 2 */
        u_char  ip_tos;                 /* type of service */
        u_short ip_len;                 /* total length */
        u_short ip_id;                  /* identification */
        u_short ip_off;                 /* fragment offset field */
        #define IP_RF 0x8000            /* reserved fragment flag */
        #define IP_DF 0x4000            /* dont fragment flag */
        #define IP_MF 0x2000            /* more fragments flag */
        #define IP_OFFMASK 0x1fff       /* mask for fragmenting bits */
        u_char  ip_ttl;                 /* time to live */
        u_char  ip_p;                   /* protocol */
        u_short ip_sum;                 /* checksum */
        struct  in_addr ip_src,ip_dst;  /* source and dest address */
};

#define IP_HL(ip)               (((ip)->ip_vhl) & 0x0f)
#define IP_V(ip)                (((ip)->ip_vhl) >> 4)

/* TCP header */
typedef u_int tcp_seq;

struct sniff_tcp {
        u_short th_sport;               /* source port */
        u_short th_dport;               /* destination port */
        tcp_seq th_seq;                 /* sequence number */
        tcp_seq th_ack;                 /* acknowledgement number */
        u_char  th_offx2;               /* data offset, rsvd */
	#define TH_OFF(th)      (((th)->th_offx2 & 0xf0) >> 4)
        u_char  th_flags;
        #define TH_FIN  0x01
        #define TH_SYN  0x02
        #define TH_RST  0x04
        #define TH_PUSH 0x08
        #define TH_ACK  0x10
        #define TH_URG  0x20
        #define TH_ECE  0x40
        #define TH_CWR  0x80
        #define TH_FLAGS        (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG|TH_ECE|TH_CWR)
        u_short th_win;                 /* window */
        u_short th_sum;                 /* checksum */
        u_short th_urp;                 /* urgent pointer */
};

struct sniff_udp {
        u_short uh_sport;               /* source port */
        u_short uh_dport;               /* destination port */
        u_short uh_length;				/*length header+data*/
        u_short uh_checksum;            /* chechsum */
      
};

//Struktura listy white i black

typedef struct Adresy {
	char Adres[15];
	char kierunek[4];
	int port_start;
	int port_stop;
	struct Adresy * nastepny;
};

//plik admin
FILE *admin;
struct Adresy *biala;
struct Adresy *czarna;

//funkcje operujace na listach black i white.

struct Adresy * wczytaj_adresy(char* plik,int porty)
{//wczytuje adresy z pliku i zwraca wskaznik do listy.
	FILE *f;
	struct Adresy *start;
	struct Adresy *teraz;
	int wynik;
	char ciag[128];
	char * tmp;
	char znak;

	f=fopen(plik,"r");
	wynik=fscanf(f,"%15s",ciag);



	if(wynik!=EOF)
	{
		start=malloc(sizeof(struct Adresy));
		start->nastepny=NULL;
		start->port_start=0;
		start->port_stop=0;

		strcpy(start->Adres,ciag);

		//powinno wczytac spacje:
		wynik=fscanf(f,"(space)");

		//powinno wczytac src lub dest
		wynik=fscanf(f,"%4s",ciag);

		
		if(strcmp(ciag,"SRC")||strcmp(ciag,"DEST"))
		{
			strcpy(start->kierunek,ciag);
		}
		
		//jesli mamy tez czytac numery portow.
		if (porty==1)
		{
			wynik=fscanf(f,"(space)");
			//przeczytalismy puste znaki
			wynik=fscanf(f,"%s,",ciag);
			//wczytalismy porty. Rozbijemy je.
			tmp = strtok (ciag,",");
			start->port_start=atoi(tmp);
			tmp = strtok (NULL, ",");
			start->port_stop=atoi(tmp);
		}

		while(znak!='n')
		{
			//czytamy wszystko do konca linii.
			wynik=fscanf(f,"%c",&znak);
		}

		teraz=start;
		wynik=fscanf(f,"%s",ciag);

		while(wynik!=EOF)
		{
			teraz->nastepny=malloc(sizeof(struct Adresy));
			teraz=teraz->nastepny;
			teraz->nastepny=NULL;
			teraz->port_start=0;
			teraz->port_stop=0;
			strcpy(teraz->Adres,ciag);

			//powinno wczytac spacje:
			wynik=fscanf(f,"(space)");

			//powinno wczytac src lub dest
			wynik=fscanf(f,"%s",ciag);

			if((strcmp(ciag,"SRC"))||(strcmp(ciag,"DEST")))
			{
				strcpy(teraz->kierunek,ciag);
			}
			
			//jesli mamy tez czytac numery portow.
			//jesli mamy tez czytac numery portow.
			if (porty==1)
			{
				wynik=fscanf(f,"(space)");
				//przeczytalismy puste znaki
				wynik=fscanf(f,"%s,",ciag);
				//wczytalismy porty. Rozbijemy je.
				tmp = strtok (ciag,",");
				teraz->port_start=atoi(tmp);
				tmp = strtok (NULL, ",");
				teraz->port_stop=atoi(tmp);
			}

			while(znak!='n')
			{
				//czytamy wszystko do konca linii.
				wynik=fscanf(f,"%c",&znak);
			}

			wynik=fscanf(f,"%s",ciag);
		}

		return start;
	}
	else
	{
		return NULL;
		//blad. plik pusty albo co.
	}
	fclose(f);
}


int lista(struct Adresy * lista,char* source,char* destination, int port_zrodlo,int port_docelowy)
{
	//zwraca 1 jesli zrodlowy lub docelowy ip sa na liscie.
	//+1 jesli kierunek sie zgadza
	//+2 jesli port sie zgadza.
	//0 jesli adresu nie ma.
	int zwroc,naj_zwroc;
	struct Adresy *teraz;
	teraz=lista;
	zwroc=0;
	naj_zwroc=0;

	//szukamy
	while ((teraz!=NULL)&&(zwrocAdres,source)==0)||(strcmp(teraz->Adres,destination)==0))
		{
			if(zwroc==0)
			{
				//ip jest na liscie
				zwroc=1;
				
			}

			if((zwroc==1)&&(((strcmp(teraz->Adres,source)==0)&&(strcmp(teraz->kierunek,"SRC")==0))||((strcmp(teraz->Adres,destination)==0)&&(strcmp(teraz->kierunek,"DEST")==0))))
			{
				//odkrylismy wlasnie wpis w ktorym kierunek sie zgadza.
				zwroc=zwroc+1;
			}

			if(((port_zrodlo!=0)||(port_docelowy!=0))&&((zwroc==1)||(zwroc==2))&&(((strcmp(teraz->kierunek,"DEST")==0)&&(port_docelowy>=teraz->port_start)&&(port_docelowyport_stop))||((strcmp(teraz->kierunek,"SRC")==0)&&(port_zrodlo>=teraz->port_start)&&(port_zrodloport_stop))))
			{
				//Odkrylismy wlasnie ze i port sie zgadza.
				zwroc=zwroc+2;
			}

		}
		
		if(zwroc>naj_zwroc)
		{
			naj_zwroc=zwroc;
		}
		
		teraz=teraz->nastepny;
	}

	return naj_zwroc;
}

int posprzataj(struct Adresy * lista)
{
	struct Adresy* tmp;
	
	while(lista!=NULL)
	{
		tmp=lista;
		lista=lista->nastepny;
		free(tmp);
	}
	
	return 0;
}

//zapisuje do pliku admin.
int zapisz(char *source,char *destination,char *prot,char *komunikat)
{
	fprintf(admin,"%s %s %s %sn",source,destination,prot,komunikat);
}

//Funkcje zwiazane z wlasciwa analiza.


void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);



int check_payload(const u_char *payload, int len)
{
	int dlugosc,i,j;

	if((payload[0]'9'))
	{
		//liczba ma byc z przedzialu 0-9
		return 1;
	}
	else
	{
		dlugosc=(len-1)/(payload[0]-48);
		j=1;
		for(i=dlugosc+1;idlugosc)
			{
				j=1;
			}
		}
	}
	
	return 0;
}



/*
 * dissect/print packet
 */

void
got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
	/* declare pointers to packet headers */
	const struct sniff_ethernet *ethernet;  /* The ethernet header [1] */
	const struct sniff_ip *ip;              /* The IP header */
	const struct sniff_tcp *tcp;            /* The TCP header */
	//const struct sniff_udp *udp;			/* The UDP header */
	const char *payload;                    /* Packet payload */
	char *source,*destination;
	char prot[10];						//nazwa protokolu

	int size_ip;
	int size_tcp;
	int size_payload;
	int wynik_biala,wynik_czarna,port_zrodlowy,port_docelowy,wynik_payload;
	
	/* define ethernet header */
	ethernet = (struct sniff_ethernet*)(packet);
	/* define/compute ip header offset */
	ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
	size_ip = IP_HL(ip)*4;
	if (size_ip ip_p) {
		case IPPROTO_TCP:
			strncpy(prot,"TCP",4);
			break;
		case IPPROTO_UDP:
			strncpy(prot,"UDP",4);
			break;
		case IPPROTO_ICMP:
			strncpy(prot,"ICMP",5);
			break;
		case IPPROTO_IP:
			strncpy(prot,"IP",3);
			break;
		default:
			strncpy(prot,"OTHER",6);
			break;
	}


	//Rozpoznajemy adresy zrodlowy i docelowy
	destination=inet_ntoa(ip->ip_src);
	source=(char*)malloc(sizeof(char)*strlen(destination));
	strncpy(source,destination,strlen(destination));
	source[strlen(destination)]='';
	destination=inet_ntoa(ip->ip_dst);
	
	//testujemy.
	wynik_czarna=lista(czarna,source,destination,0,0);
	
	if(wynik_czarna>1)
	{
		//odrzucamy z powodu warunku 1 - jest w pliku_bad
		zapisz(source,destination,prot,"BAD SRC/DEST IP");
	}
	else
	{
		if (ip->ip_p==IPPROTO_TCP || ip->ip_p==IPPROTO_UDP) //tcp lub udp
		{
			tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);
			port_zrodlowy=ntohs(tcp->th_sport);
			port_docelowy=ntohs(tcp->th_dport);
			//testujemy.
			wynik_biala=lista(biala,source,destination,port_zrodlowy,port_docelowy);
			
			if((wynik_biala==1)||(wynik_biala==2)) //jest na liscie, ale nie zgadza sie port. (jesli by sie zgadzal byloby 3 albo 4)
			{
				//odrzucamy z powodu niespelnienia warunku 2.
				zapisz(source,destination,prot,"BAD SRC/DEST PORT");
			}
			else
			{
				//ok. przeszlismy pierwsze dwa testy. teraz czy format pliku sie zgadza.
				wynik_payload=0;
				
				if (ip->ip_p==IPPROTO_TCP)
				{
					size_tcp = TH_OFF(tcp)*4;
					if (size_tcp ip_len) - (size_ip + size_tcp);
					
					if (size_payload > 0) 
					{
						wynik_payload=check_payload(payload,size_payload);
						//if(wynik_payload==2)
						//	printf("%snnnn---------n",payload);
						
					}
				}
				
				if(wynik_payload==1)
				{
					zapisz(source,destination,prot,"BAD PACKET FORMAT, MISSING NUMBER");
				}
				else if (wynik_payload==2)
				{
					zapisz(source,destination,prot,"BAD PACKET FORMAT, NOT MATCHING DATA");
				}
				else
				{
					//PAKIET OK!!
					pcap_dump(plik, header, packet);//przepuszaczamy
					zapisz(source,destination,prot,"PACKET OK");
				}
			}
		}
		
	}
	
	return;
}




/*main-----------------------------------------------------------------*/
/*main-----------------------------------------------------------------*/
/*main-----------------------------------------------------------------*/
int main(int argc, char **argv)
{
	//char *dev = NULL;			/* capture device name */
	char errbuf[PCAP_ERRBUF_SIZE];		/* error buffer */
	pcap_t *handle;				/* packet capture handle */

	if(argc==6)
	{

		//wczytujemy dane z odpowiednich list.
		czarna=wczytaj_adresy(argv[4],0);
		biala=wczytaj_adresy(argv[5],1);

	  	if (!(handle=pcap_open_offline(argv[1], errbuf)))
		 {
			perror(errbuf);
			exit(1);
		 }

	  	if (!(plik=pcap_dump_open(handle, argv[2])))
		 {
			printf("BLADn");
			exit(1);
		 }
		
		admin=fopen(argv[3],"w");

		if (pcap_dispatch(handle, -1/*num_packets*/, got_packet,(u_char *) admin));

		fclose(admin);
		pcap_dump_close(plik);
		pcap_close(handle);
		//sprzatamy pamiec:
		posprzataj(biala);
		posprzataj(czarna);
		
	}
	else
	{
		printf("Podaj 5 parametrow!!n");
		return 1;
	}
	return 0;
}

Wymiana Drzwi

Długo i namiętnie zabierałem się do wymiany drzwi kierowcy w moim maleństwie.

Spytacie mnie dlaczego postanowiłem to robić? Otóż dlatego:

Naklejki w postaci dziur po kulach przestały wystarczać jako substytut naprawy, więc coś z tym fantem trzeba było zrobić.

Na Allegro zanabyłem więc za 200 zł całkiem porządne drzwi w odpowiednim kolorze, przetrzymałem je parę miesięcy w piwnicy, ale nadeszła TA pora.

Przy okazji postawiłem sobie cele:

    1.Naturalnie wymiana drzwi

2.Zawalczenie z zacinającym się na mrozie centralnym

3.Poprowadzenie kabli pod nowe głośniki

4.Diody w klamkach zewnętrznych. A co!

5.Wygłuszenie drzwi

Continue reading “Wymiana Drzwi”

Archiwizowanie rozmów telefonicznych

Moja praca wymaga bardzo dużej ilości kontaktów telefonicznych. Klienci często dyktują mi różne informacje, albo mówią różne rzeczy których potem nie pamiętają.. No nie jest czasem ciekawie

Idąc za przykładem naszego byłego ministra sprawiedliwości postanowiłem Uziobrowić swój telefon. Jako że posiadam tzw. HTC Wizarda (SPV M3000) i ROM WM6 Pathfinder 3.2 NxS, (czyli w skrócie – mój telefon to PDA z Windows Mobile), mogłem uruchomić na nim program PMRecorder, nagrywający wszystkie rozmowy. Program jest darmowy, jednak nagrywa rozmowy w dziwnym formacie.

Więc, do rzeczy. Napisałem program, który przekształci katalog z plikami PMRecordera i BSCallTimes.xml (plik z historią rozmów WM6) na pliki do otwarcia w MediaPlayerze a dane wrzuci do bazy mysql.

Jest to skrypt PHP. Wiem że to szalone, głupie i bezsensowne, ale lubię PHP, mam dostęp do serwera i odpalam go bezproblemowo w Shellu.

Warto zwiększyć limit czasu wykonywania i pamięci w php.ini
Schemat tabeli w bazie danych:

CREATE TABLE `owczarek_rozmowy` (`id` int(11) NOT NULL auto_increment,`wav_file` varchar(16) NOT NULL default '',`type` text NOT NULL,`time` int(12) NOT NULL default '0',
`length` int(6) NOT NULL default '0',
`number` varchar(12) NOT NULL default '',
`caller` text NOT NULL,
`number_type` char(1) NOT NULL default '',
`note` text NOT NULL,
PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

A oto właściwy skrypt:

$input="./input";

$sql_host='localhost';
$sql_user='artpi';
$sql_pass='5155';
$sql_base='owczarek';
$sql_table='owczarek_rozmowy';
$wav_archive="./archiwum";

//A great function i found at http://www.bin-co.com/php/scripts/xml2array/

function xml2array($contents, $get_attributes=1) {
    if(!$contents) return array();

    if(!function_exists('xml_parser_create')) {
        //print "'xml_parser_create()' function not found!";
        return array();
    }
    //Get the XML parser of PHP - PHP must have this module for the parser to work
    $parser = xml_parser_create();
    xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
    xml_parser_set_option( $parser, XML_OPTION_SKIP_WHITE, 1 );
    xml_parse_into_struct( $parser, $contents, $xml_values );
    xml_parser_free( $parser );

    if(!$xml_values) return;//Hmm...

    //Initializations
    $xml_array = array();
    $parents = array();
    $opened_tags = array();
    $arr = array();

    $current = &$xml_array;

    //Go through the tags.
    foreach($xml_values as $data) {
        unset($attributes,$value);//Remove existing values, or there will be trouble
        extract($data);//We could use the array by itself, but this cooler.

        $result = '';
        if($get_attributes) {//The second argument of the function decides this.
            $result = array();
            if(isset($value)) $result['value'] = $value;

            //Set the attributes too.
            if(isset($attributes)) {
                foreach($attributes as $attr => $val) {
                    if($get_attributes == 1) $result['attr'][$attr] = $val; //Set all the attributes in a array called 'attr'
                    /**  :TODO: should we change the key name to '_attr'? Someone may use the tagname 'attr'. Same goes for 'value' too */
                }
            }
        } elseif(isset($value)) {
            $result = $value;
        }

        //See tag status and do the needed.
        if($type == "open") {//The starting of the tag ''
            $parent[$level-1] = &$current;

            if(!is_array($current) or (!in_array($tag, array_keys($current)))) { //Insert New tag
                $current[$tag] = $result;
                $current = &$current[$tag];

            } else { //There was another element with the same tag name
                if(isset($current[$tag][0])) {
                    array_push($current[$tag], $result);
                } else {
                    $current[$tag] = array($current[$tag],$result);
                }
                $last = count($current[$tag]) - 1;
                $current = &$current[$tag][$last];
            }

        } elseif($type == "complete") { //Tags that ends in 1 line ''
            //See if the key is already taken.
            if(!isset($current[$tag])) { //New Key
                $current[$tag] = $result;

            } else { //If taken, put all things inside a list(array)
                if((is_array($current[$tag]) and $get_attributes == 0)//If it is already an array...
                        or (isset($current[$tag][0]) and is_array($current[$tag][0]) and $get_attributes == 1)) {
                    array_push($current[$tag],$result); // ...push the new element into that array.
                } else { //If it is not an array...
                    $current[$tag] = array($current[$tag],$result); //...Make it an array using using the existing value and the new value
                }
            }

        } elseif($type == 'close') { //End of tag ''
            $current = &$parent[$level-1];
        }
    }

    return($xml_array);
} 

	mysql_connect($sql_host,$sql_user,$sql_pass);
	mysql_select_db($sql_base);

	//If there's a call log file in input directory.

	if(file_exists($input."/BSCallTimes.xml"))
	{

		echo "Processing ".$input."/BSCallTimes.xml file n";
		$fd=fopen($input."/BSCallTimes.xml","r");
		$content=fread($fd,filesize($input."/BSCallTimes.xml"));
		fclose($fd);

		$array=xml2array($content);

		$calls=$array['BSCallTimesLog']['Call'];
		for($i=0;$i
		{
			$call['type']=$calls[$i]['attr']['Type'];
			$call['length']=$calls[$i]['attr']['RoundSeconds'];

			// If it's an sms, let's put size instead of length.
			if(substr($call['type'],0,3)=='msg')
				$call['length']=$calls[$i]['attr']['Amount'];

			//Time to parse date & time
			$date=explode("/",$calls[$i]['attr']['Date']);
			$time=explode(".",$calls[$i]['attr']['Time']);
			$time2=explode(":",$time[0]);
			$call['time']=mktime($time2[0],$time2[1],$time[1],$date[1],$date[2],$date[0]);

			$call['number']=$calls[$i]['Number']['value'];
			$call['caller']=$calls[$i]['Desc']['value'];

			//What the hell do we need ? for?
			if($call['caller']=='?')
				$call['caller']='';

			$wynik=mysql_query("SELECT * FROM $sql_table WHERE time='".$call['time']."';");

			if(mysql_num_rows($wynik)>0)
			{
				//Is it already in the databese, but maybe we put it during call record parsing.
				$wiersz=mysql_fetch_array($wynik);

				if(strlen($wiersz['type'])<4)
				{

					//Yup, we can update the data.
					mysql_query("UPDATE $sql_table SET type='".$call['type']."',length='".$call['length']."',number='".$call['number']."' WHERE time='".$call['time']."';");
					echo "At:".time()." updated call at [".$call['time']."] - Type:[".$call['type']."], Length:[".$call['length']."], Number: [".$call['number']."]n";
				}

			}
			else
			{
					//Lets insert some data.
					mysql_query("INSERT INTO $sql_table SET type='".$call['type']."',length='".$call['length']."',number='".$call['number']."',time='".$call['time']."',caller='".$call['caller']."';");
					echo "At: ".time()." inserted call at [".$call['time']."] - Type:[".$call['type']."], Length:[".$call['length']."], Number: [".$call['number']."], Caller: [".$call['caller']."]n";			

			}

		}
		echo "BSCallTimes Processed.n";
	}

	//So, now that BSCallTimes file is processed, let's process other files.

		$directory = opendir($input);
 		while($file = readdir($directory)) {

			//If it's PMRecorder file:
 			If(substr($file,-2)=='wv')
			{

				$naz=explode(".",$file);

				//So we don't do this again:
				if(!file_exists($wav_archive."/".$naz[0].".wav"))
				{

					$pliczek=$input."/".$file;

					echo "Processing file ".$pliczek."n";

					$fd=fopen($pliczek,"r");
					$content=fread($fd,filesize($pliczek));
					fclose($fd);

					$wav=strstr($content,"RIFF");

					$fd=fopen($wav_archive."/".$naz[0].".wav","w");
					fwrite($fd,$wav);
					fclose($fd);

					echo "Wav file saved at ".$wav_archive."/".$naz[0].".wav"."n";

					$naglowki=substr($content,24,strpos($content,"RIFF")-24);
					$nag=explode(chr(0).chr(0).chr(100),$naglowki);

					$czysc1=array(chr(0),chr(100));
					$czysc2=array("e","I","O","f",chr(0),chr(127));

					//PMRecorder file name
					$data[0]=$naz[0];
					//Unix time
					$data[1]=mktime($naz[0][8].$naz[0][9],$naz[0][10].$naz[0][11],$naz[0][12].$naz[0][13],$naz[0][0].$naz[0][1],$naz[0][2].$naz[0][3],$naz[0][4].$naz[0][5].$naz[0][6].$naz[0][7]);
					//Caller name
					$data[2]=str_replace($czysc1,"",$nag[0]);
					//Caller number
					$data[3]=str_replace($czysc2,"",$nag[1]);
					preg_match ("#([a-z])#is",$data[3],$tmp);
					//Number type (h/m/...)
					$data[4]=$tmp[1];
					//Filtered number
					$data[3]=preg_replace("#([a-z])#is","",$data[3]);

					//Once again some sql:

					$wynik=mysql_query("SELECT * FROM $sql_table WHERE time >'".($data[1]-4)."' AND time<'".($data[1]+1)."';");

					//Why so strange where clause? PMRecorder is a bit retarded in comparison with BSCAlltimes :)		

					if(mysql_num_rows($wynik)>0)
					{
						//Is it already in the databese, but maybe we put it during call record parsing.
						$wiersz=mysql_fetch_array($wynik);

						if(strlen($wiersz['wav_file'])<1)
						{
							//Yup, we can update the data.
							mysql_query("UPDATE $sql_table SET wav_file='".$data[0]."',number_type='".$data[4]."',caller='".$data[2]."' WHERE time>'".($data[1]-4)."' AND time<'".($data[1]+1)."';");
							echo "At:".time()." updated call at [".$data[1]."] - Wav file:[".$data[0]."], Caller:[".$data[2]."],Number type:[".$data[4]."],n";
						}

					}
					else
					{
							//Call wasnt inserted during bscalltimes file parsing. Let's do this!
							//Lets insert some data.
							mysql_query("INSERT INTO $sql_table SET wav_file='".$data[0]."',number_type='".$data[4]."',caller='".$data[2]."',time='".$data[1]."',number='".$data[3]."';");
							echo "At:".time()." inserted call at [".$data[1]."] - Wav file:[".$data[0]."], Caller:[".$data[2]."],Number type:[".$data[4]."],Number:[".$data[3]."]n";		

					}

					echo "File ".$pliczek." processed.n";
				}

			}

 		}
		closedir($directory);

print($log);