#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <utime.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <ctype.h>
#ifdef IPV6_V6ONLY
// #include <punycode.h>
#endif
#include <stdlib.h>
#include <strings.h>
#include <openssl/bio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/x509_vfy.h>
#include <arpa/nameser.h>
#include <resolv.h>
#include <unistd.h>
#include <dirent.h>
#include <netdb.h>
#include "tools.h"

#define FTP_LOGFILE "/big/GIX_INETD/logs/ftp.log"

void ftp_logger(const char *fmt, ...){
        char p[102400];
        struct stat st;
        FILE *log;
        va_list ap;
        struct timeval tv;
        struct tm _tm;
        struct tm *tm;
        char datestamp[512];
        gettimeofday(&tv,NULL);
        tm = localtime_r(&tv.tv_sec,&_tm);
        sprintf(datestamp,"[%04d-%02d-%02d %02d:%02d:%02d.%06d]{%d}",
                tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
                tm->tm_hour, tm->tm_min, tm->tm_sec, tv.tv_usec,
                getpid());

        va_start(ap,fmt);
        vsnprintf(p,102400,fmt,ap);
        va_end(ap);

        log = fopen(FTP_LOGFILE,"a");
        if ( log == NULL ) return;
        fprintf(log,"%s %s",datestamp,p);
        fflush(log);
        fclose(log);
}



// preferred_family is either: AF_UNSPEC, AF_INET4, AF_INET6
// sock_type


int get_sockaddr(int preferred_family, int sock_type, char *hostname, unsigned short port, struct sockaddr **sock_addr, int *sock_family, int *sock_addr_len, char *printable, int printable_len){
	if ( printable ) bzero(printable,printable_len);
	if ( strstr(hostname,":") == NULL && inet_addr(hostname) == INADDR_NONE ){
			char portname[1024];
			struct addrinfo hints;
			struct addrinfo *res;
			bzero(&hints,sizeof(hints));
			hints.ai_family = preferred_family;
			hints.ai_socktype = sock_type;
			sprintf(portname,"%d",port);
			if ( getaddrinfo(hostname,portname,&hints,&res) ){
				return(-1);
			}
			*sock_family = res->ai_family;
			*sock_addr_len = res->ai_addrlen;
			*sock_addr = (struct sockaddr *)malloc(res->ai_addrlen);
			memcpy((void *)*sock_addr,(void *)res->ai_addr,res->ai_addrlen);
			if ( printable ){
				if ( *sock_family == AF_INET ){
					struct sockaddr_in *socky;
					socky = (struct sockaddr_in *)*sock_addr;	
					inet_ntop(*sock_family,&(socky->sin_addr),printable,printable_len);
				}
				if ( *sock_family == AF_INET6 ){
					struct sockaddr_in6 *socky;
					socky = (struct sockaddr_in6 *)*sock_addr;	
					inet_ntop(*sock_family,&(socky->sin6_addr),printable,printable_len);
				}
			}
			return(0);
					
	} else {
		if ( inet_addr(hostname) != INADDR_NONE ){
			struct sockaddr_in socky; 
			*sock_family = AF_INET;			
			socky.sin_family = AF_INET;
			socky.sin_addr.s_addr = inet_addr(hostname);
			socky.sin_port = htons(port);	
			*sock_addr = (struct sockaddr *)malloc(sizeof(socky));
			*sock_addr_len = sizeof(socky);
			memcpy((void *)*sock_addr,&socky,sizeof(socky));
			if ( printable ){
				if ( *sock_family == AF_INET ){
					struct sockaddr_in *socky;
					socky = (struct sockaddr_in *)*sock_addr;	
					inet_ntop(*sock_family,&(socky->sin_addr),printable,printable_len);
				}
				if ( *sock_family == AF_INET6 ){
					struct sockaddr_in6 *socky;
					socky = (struct sockaddr_in6 *)*sock_addr;	
					inet_ntop(*sock_family,&(socky->sin6_addr),printable,printable_len);
				}
			}
			return(0);
		} else {
			char portname[1024];
			struct addrinfo hints;
			struct addrinfo *res;
			bzero(&hints,sizeof(hints));
#ifdef AI_NUMERICSERV
			hints.ai_flags = AI_NUMERICSERV;
#endif
			hints.ai_family = AF_INET6;
			hints.ai_socktype = sock_type;
			sprintf(portname,"%d",port);
			*sock_family = AF_INET6;			
			if ( getaddrinfo(hostname,portname,&hints,&res) ){
				return(-1);
			}
			*sock_addr = (struct sockaddr *)malloc(res->ai_addrlen);
			memcpy((void *)*sock_addr,(void *)res->ai_addr,res->ai_addrlen);
			*sock_addr_len = res->ai_addrlen;
			if ( printable ){
				if ( *sock_family == AF_INET ){
					struct sockaddr_in *socky;
					socky = (struct sockaddr_in *)*sock_addr;	
					inet_ntop(*sock_family,&(socky->sin_addr),printable,printable_len);
				}
				if ( *sock_family == AF_INET6 ){
					struct sockaddr_in6 *socky;
					socky = (struct sockaddr_in6 *)*sock_addr;	
					inet_ntop(*sock_family,&(socky->sin6_addr),printable,printable_len);
				}
			}
			return(0);
		}
	}
	
}






int ftp_write_bytes(int sock, SSL *ssl, char *buf, int len){
        int re_sent;
        int to_send;

        re_sent = 0;
        to_send = len;
        if ( ssl != NULL ){
                while ( to_send > 0 ){
                        int r_sent;
                        r_sent = SSL_write(ssl,&buf[re_sent],to_send);
                        if ( r_sent <= 0 ){
                                if ( re_sent == 0 ) return(-1);
                                else return(re_sent);
                        }
                        to_send -= r_sent;
                        re_sent += r_sent;
                }
        } else {
                while ( to_send > 0 ){
                        int r_sent;
                        r_sent = send(sock,&buf[re_sent],to_send,0);
                        if ( r_sent <= 0 ){
                                if ( re_sent == 0 ) return(-1);
                                else return(re_sent);
                        }
                        to_send -= r_sent;
                        re_sent += r_sent;
                }
        }
        return(len);
}

int ftp_read_bytes(int sock, SSL *ssl, char *buf, int len){
        int re_recvd;
        int to_recv;

        re_recvd = 0;
        to_recv = len;
        if ( ssl != NULL ){
                while ( to_recv > 0 ){
                        int r_recvd;
                        r_recvd = SSL_read(ssl,&buf[re_recvd],to_recv);
                        if ( r_recvd <= 0 ){
                                if ( re_recvd == 0 ) return(-1);
                                else return(re_recvd);
                        }
                        to_recv -= r_recvd;
                        re_recvd += r_recvd;
                }
        } else {
                while ( to_recv > 0 ){
                        int r_recvd;
                        r_recvd = recv(sock,&buf[re_recvd],to_recv,0);
                        if ( r_recvd <= 0 ){
                                if ( re_recvd == 0 ) return(-1);
                                else return(re_recvd);
                        }
                        to_recv -= r_recvd;
                        re_recvd += r_recvd;
                }
        }
        return(len);
}


int ftp_read_line(int sock, SSL *ssl, char *buf,int len){
        int pos;
        int retval;
        pos = 0;
        while ( pos < len ){
                if ( (retval = ftp_read_bytes(sock,ssl,&buf[pos],1)) < 0 ){
                        if ( pos == 0 ){
                                return(-1);
                        } else {
                                buf[pos] = '\0';
                                return(pos);
                        }
                }
                if ( retval == 0 ){
                        buf[pos] = '\0';
                        return(pos);
                }
                if ( buf[pos] == '\n' ){
                        pos++;
                        buf[pos] = '\0';
                        return(pos);
                }
                pos++;

        }
        buf[pos] = '\0';
        return(pos);
}

#define FTP_PORT 21


int ftp_response_code(char *ptr){
	if ( strlen(ptr) < 5 ) return(-1);
	if ( ptr[3] == '-' ) return(-1);
	if ( ptr[3] != '-' ) return(atoi(ptr));
}
int ftp_dir_internal(char *server, char *user, char *pwd, char *remote_dir, char *local_file,int direction){
	int sock;
	struct sockaddr_in socky;
	struct hostent *hp;
	char buf[1024];
	int response_code;
	int data_sock;
	int data_port;
	char data_ip[128];
	struct sockaddr_in data_socky;
	ftp_logger("FTP(%s) (User: [%s], Pass: [%s]) Remote-Directory: [%s] LOCAL-FILE: [%s] Action: [%s]\n",
		server,user,pwd,remote_dir,local_file == NULL ? "(null)" : local_file , (direction == FTP_TRANSFER_SEND) ? "MKDIR" : "LIST");
	socky.sin_port = htons(FTP_PORT);
	socky.sin_family = AF_INET;
	if ( inet_addr(server) == INADDR_NONE ){
		hp = gethostbyname(server);
		if ( hp == NULL ){
			ftp_logger("FTP(%s:%d) Cannot resolve hostname '%s'\n",__FILE__,__LINE__,server);
			return(-1);
		}
		socky.sin_addr = *((struct in_addr *)hp->h_addr);
	} else {
		socky.sin_addr.s_addr = inet_addr(server);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connecting to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	sock = socket(AF_INET,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("(%s:%d) Cannot create socket!\n",__FILE__,__LINE__);
		return(-2);
	}
	if ( connect(sock,(struct sockaddr *)&socky,sizeof(socky)) < 0  ){
		ftp_logger("(%s:%d) Cannot connect socket!\n",__FILE__,__LINE__);
		return(-2);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connected to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}

#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif


	sprintf(buf,"USER %s\r\n",user);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	sprintf(buf,"PASS %s\r\n",pwd);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 230 ){
		close(sock);
		ftp_logger("FTP(%s:%d) LOGIN FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}

	sprintf(buf,"TYPE I\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 250 ){
		close(sock);
		ftp_logger("FTP(%s:%d) Setting binary-mode FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}
	if ( direction == FTP_TRANSFER_RECV ){
		sprintf(buf,"PASV\r\n");
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		ftp_write_bytes(sock,NULL,buf,strlen(buf));
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
		if ( response_code != 227 ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
			return(-1);
		}
		{
			char *ptr;
			int a,b,c,d;
			int port_low;
			int port_high;

			ptr = buf;
			while ( *ptr && *ptr != '(' ) ptr++;
			if ( *ptr != '(' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-first-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			a = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-second-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			b = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-third-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			c = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-fourth-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			d = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-high declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			port_high = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-low declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			port_low = atoi(ptr);
			sprintf(data_ip,"%d.%d.%d.%d",a,b,c,d);
			data_socky.sin_family = AF_INET;
			data_socky.sin_addr.s_addr = inet_addr(data_ip);
			data_port = port_low + port_high * 256;
			data_socky.sin_port = htons((short)data_port);
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) Data-Connection: [%s:%d]\n",inet_ntoa(socky.sin_addr),FTP_PORT,data_ip,data_port);
#endif
			data_sock = socket(AF_INET,SOCK_STREAM,0);
			if ( data_sock < 0 ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting cannot create socket for passive-transfer\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			if ( connect(data_sock,(struct sockaddr *)&data_socky,sizeof(data_socky)) < 0 ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot connect to data-socket at (%s:%d)\n",inet_ntoa(socky.sin_addr),FTP_PORT,data_ip,data_port);
				return(-1);
			}
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) DATA-SOCKET connected to: [%s:%d]\n",inet_ntoa(socky.sin_addr),FTP_PORT,data_ip,data_port);
#endif
		}
		{
			int bytes_in;
			int c;
			FILE *fp;
			unlink(local_file);
			fp = fopen(local_file,"w");
			if ( fp == NULL ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) [%s: %d] Cannot open local-file for writing\n",inet_ntoa(socky.sin_addr),FTP_PORT, __FILE__,__LINE__,local_file);
				return(-1);
			}	
			sprintf(buf,"LISTRAW %s\r\n",remote_dir);
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
			ftp_write_bytes(sock,NULL,buf,strlen(buf));
			while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
				ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
				if ( (response_code = ftp_response_code(buf)) != -1 ){
					break;
				}
			}
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
			if ( response_code != 150 ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot retrieve data\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file);
				return(-1);
			}
			bytes_in = 0;
			while ( ftp_read_bytes(data_sock,NULL,(char *)&c,1) == 1 ){
				bytes_in++;
				fputc(c,fp);
			}
			fclose(fp);
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) Received: %d Bytes\n",inet_ntoa(socky.sin_addr),FTP_PORT,bytes_in);
#endif
			while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
				ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
				if ( (response_code = ftp_response_code(buf)) != -1 ){
					break;
				}
			}
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif

			if ( response_code != 226 ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot retrieve data(no 226 response after transfer)\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file);
				return(-1);
			}
		}
	} else { 
		// MKDIR
	}
	// End the connection :-)
	sprintf(buf,"QUIT\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	close(sock);
	return(0);	
	
}

int ftp_dir(char *server, char *user, char *pwd, char *remote_dir, char *local_file,int direction){
	int sock;
	struct sockaddr_in socky;
	struct sockaddr *sockaddr;
	int sock_addr_family;
	int sock_addr_len;
	struct hostent *hp;
	char buf[1024];
	int response_code;
	int data_sock;
	int data_port;
	char data_ip[1024];
	struct sockaddr_in data_socky;
	struct sockaddr_in6 data_socky6;
	char printable[2048];

	ftp_logger("FTP(%s) (User: [%s], Pass: [%s]) Remote-Directory: [%s] LOCAL-FILE: [%s] Action: [%s]\n",
		server,user,pwd,remote_dir,local_file == NULL ? "(null)" : local_file , (direction == FTP_TRANSFER_SEND) ? "MKDIR" : "LIST");


	if ( get_sockaddr(AF_UNSPEC,SOCK_STREAM,server,FTP_PORT,&sockaddr,&sock_addr_family,&sock_addr_len,printable,1024) ){
		ftp_logger("FTP(%s) Cannot get address\n",server);
		return(-1);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connecting to '%s:%d'\n",__FILE__,__LINE__,printable,FTP_PORT);
#endif

	sock = socket(sock_addr_family,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("(%s:%d) Cannot create socket!\n",__FILE__,__LINE__);
		return(-2);
	}
	if ( connect(sock,sockaddr,sock_addr_len) < 0  ){
		ftp_logger("(%s:%d) Cannot connect socket!\n",__FILE__,__LINE__);
		return(-2);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connected to '%s:%d' Remote-Directory: [%s], Local-File: [%s]\n",__FILE__,__LINE__,printable,FTP_PORT,remote_dir,local_file != NULL ? local_file : "null" );
#endif

	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}

#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif


	sprintf(buf,"USER %s\r\n",user);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
	sprintf(buf,"PASS %s\r\n",pwd);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
	if ( response_code != 230 ){
		close(sock);
		ftp_logger("FTP(%s:%d) LOGIN FAILED!\n",printable,FTP_PORT);
		return(-1);
	}

	sprintf(buf,"TYPE I\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
	if ( response_code != 250 ){
		close(sock);
		ftp_logger("FTP(%s:%d) Setting binary-mode FAILED!\n",printable,FTP_PORT);
		return(-1);
	}
	if ( direction == FTP_TRANSFER_RECV ){
		if ( sock_addr_family == AF_INET6 ){
			sprintf(buf,"EPSV\r\n");
		} else {
			sprintf(buf,"PASV\r\n");
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
		ftp_write_bytes(sock,NULL,buf,strlen(buf));
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
		if ( response_code != 227 && response_code != 229 ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED!\n",printable,FTP_PORT);
			return(-1);
		}

		if ( response_code == 229 ){
			struct sockaddr *addr_data;
			int data_family;
			int data_addr_len;
			char *ptr;
			ptr = buf;
			while ( *ptr && *ptr != '|' ) ptr++;
			if ( *ptr != '|' ) {
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No passive-connection declared)!\n",printable,FTP_PORT);
				return(-1);
			}
			while ( *ptr && !isdigit(*ptr) ) ptr++;
			if ( !isdigit(*ptr) ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Port declared)!\n",printable,FTP_PORT);
				return(-1);
			}	
			data_port = atoi(ptr);
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) Remote-Port: [%d]\n",printable,FTP_PORT,data_port);
#endif
			if ( get_sockaddr(AF_INET6,SOCK_STREAM,server,data_port,&addr_data,&data_family,&data_addr_len,data_ip,1024) ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Addr available)!\n",printable,FTP_PORT);
				return(-1);
			}
			data_sock = socket(data_family,SOCK_STREAM,0);
			if ( data_sock < 0 ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting cannot create socket for passive-transfer\n",printable,FTP_PORT);
				return(-1);
			}
			if ( connect(data_sock,(struct sockaddr *)addr_data,data_addr_len) < 0 ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot connect to data-socket at (%s:%d)\n",printable,FTP_PORT,data_ip,data_port);
				return(-1);
			}
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) DATA-SOCKET connected to: [%s:%d]\n",printable,FTP_PORT,data_ip,data_port);
#endif

		}
		
		if ( response_code == 227 ) {
			char *ptr;
			int a,b,c,d;
			int port_low;
			int port_high;

			ptr = buf;
			while ( *ptr && *ptr != '(' ) ptr++;
			if ( *ptr != '(' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-first-byte declared)!\n",printable,FTP_PORT);
				return(-1);
			}
			ptr++;
			a = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-second-byte declared)!\n",printable,FTP_PORT);
				return(-1);
			}
			ptr++;
			b = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-third-byte declared)!\n",printable,FTP_PORT);
				return(-1);
			}
			ptr++;
			c = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-fourth-byte declared)!\n",printable,FTP_PORT);
				return(-1);
			}
			ptr++;
			d = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-high declared)!\n",printable,FTP_PORT);
				return(-1);
			}
			ptr++;
			port_high = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-low declared)!\n",printable,FTP_PORT);
				return(-1);
			}
			ptr++;
			port_low = atoi(ptr);
			sprintf(data_ip,"%d.%d.%d.%d",a,b,c,d);
			data_socky.sin_family = AF_INET;
			data_socky.sin_addr.s_addr = inet_addr(data_ip);
			data_port = port_low + port_high * 256;
			data_socky.sin_port = htons((short)data_port);
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) Data-Connection: [%s:%d]\n",printable,FTP_PORT,data_ip,data_port);
#endif
			data_sock = socket(AF_INET,SOCK_STREAM,0);
			if ( data_sock < 0 ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting cannot create socket for passive-transfer\n",printable,FTP_PORT);
				return(-1);
			}
			if ( connect(data_sock,(struct sockaddr *)&data_socky,sizeof(data_socky)) < 0 ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot connect to data-socket at (%s:%d)\n",printable,FTP_PORT,data_ip,data_port);
				return(-1);
			}
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) DATA-SOCKET connected to: [%s:%d]\n",printable,FTP_PORT,data_ip,data_port);
#endif
		}
		{
			int bytes_in;
			int c;
			FILE *fp;
			unlink(local_file);
			fp = fopen(local_file,"w");
			if ( fp == NULL ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) [%s:%d] Cannot open local-file for writing[%s] (%s)\n",printable,FTP_PORT,__FILE__,__LINE__,local_file,strerror(errno));
				return(-1);
			}	
			sprintf(buf,"LIST %s\r\n",remote_dir);
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
			ftp_write_bytes(sock,NULL,buf,strlen(buf));
			while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
				ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
				if ( (response_code = ftp_response_code(buf)) != -1 ){
					break;
				}
			}
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
			if ( response_code != 150 ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot retrieve data\n",printable,FTP_PORT,local_file);
				return(-1);
			}
			bytes_in = 0;
			while ( ftp_read_bytes(data_sock,NULL,(char *)&c,1) == 1 ){
				bytes_in++;
				fputc(c,fp);
			}
			fclose(fp);
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) Received: %d Bytes\n",printable,FTP_PORT,bytes_in);
#endif
			while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
				ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
				if ( (response_code = ftp_response_code(buf)) != -1 ){
					break;
				}
			}
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif

			if ( response_code != 226 ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot retrieve data(no 226 response after transfer)\n",printable,FTP_PORT,local_file);
				return(-1);
			}
		}
	} else { 
		// MKDIR
		sprintf(buf,"MKD %s\r\n",remote_dir);
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
		ftp_write_bytes(sock,NULL,buf,strlen(buf));
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
		if ( response_code < 200 || response_code > 299 ){
			close(sock);
			return(-1);
		}
	}
	// End the connection :-)
	sprintf(buf,"QUIT\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
	close(sock);
	return(0);	
	
}

void cleanup_dir(char *dirname){
	struct dirent *diry;
	DIR *dir;

	ftp_logger("CLEANING: [%s]\n",dirname);

	dir = opendir(dirname);
	if ( dir == NULL ){
	 mkdir(dirname,00777);
	 return;
	}

	while ( (diry = readdir(dir)) != NULL ){
		char fname[1024];
		struct stat st;
		if ( strcmp(diry->d_name,".") == 0 ) continue;
		if ( strcmp(diry->d_name,"..") == 0 ) continue;
		sprintf(fname,"%s/%s",dirname,diry->d_name);
		if ( stat(fname,&st) ) continue;
#ifdef FTP_DEBUG
		ftp_logger("CLEANUP_DIR: Processing: [%s]\n",fname);
#endif
		if ( S_ISDIR(st.st_mode) ){
			cleanup_dir(fname);
			rmdir(fname);
			continue;
		}
		unlink(fname);
	}	
	closedir(dir);
}

int ftp_miupd(char *server, char *user, char *pwd, char *local_file, char *remote_file,char *wildcard1, char *wildcard2){
	FILE *fp;
	int sock;
	struct sockaddr_in socky;
	struct hostent *hp;
	char buf[1024];
	int response_code;
	int data_sock;
	int data_port;
	char data_ip[1024];

	struct sockaddr_in data_socky;
	ftp_logger("FTP(%s) (User: [%s], Pass: [%s]) Remote-Directory: [%s] LOCAL-FILE: [%s] Wildcard1: [%s] Wildcard2: [%s]\n",
		server,user,pwd,remote_file,local_file == NULL ? "(null)" : local_file , wildcard1,wildcard2);
	socky.sin_port = htons(FTP_PORT);
	socky.sin_family = AF_INET;
	if ( inet_addr(server) == INADDR_NONE ){
		hp = gethostbyname(server);
		if ( hp == NULL ){
			ftp_logger("FTP(%s:%d) Cannot resolve hostname '%s'\n",__FILE__,__LINE__,server);
			return(-1);
		}
		socky.sin_addr = *((struct in_addr *)hp->h_addr);
	} else {
		socky.sin_addr.s_addr = inet_addr(server);
	}


	fp = fopen(local_file,"r");
	if ( fp == NULL ){
		ftp_logger("(%s:%d)  Cannot open local-file (%s)\n",__FILE__,__LINE__,local_file);
		return(-1);
	}
	fclose(fp);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connecting to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	sock = socket(AF_INET,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("(%s:%d) Cannot create socket!\n",__FILE__,__LINE__);
		return(-2);
	}
	if ( connect(sock,(struct sockaddr *)&socky,sizeof(socky)) < 0  ){
		ftp_logger("(%s:%d) Cannot connect socket!\n",__FILE__,__LINE__);
		return(-2);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connected to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}

#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif


	sprintf(buf,"USER %s\r\n",user);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	sprintf(buf,"PASS %s\r\n",pwd);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 230 ){
		close(sock);
		ftp_logger("FTP(%s:%d) LOGIN FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}

	sprintf(buf,"TYPE I\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 250 ){
		close(sock);
		ftp_logger("FTP(%s:%d) Setting binary-mode FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}
	if ( 1 ){
		sprintf(buf,"PASV\r\n");
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		ftp_write_bytes(sock,NULL,buf,strlen(buf));
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
		if ( response_code != 227 ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
			return(-1);
		}
		{
			char *ptr;
			int a,b,c,d;
			int port_low;
			int port_high;

			ptr = buf;
			while ( *ptr && *ptr != '(' ) ptr++;
			if ( *ptr != '(' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-first-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			a = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-second-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			b = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-third-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			c = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-fourth-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			d = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-high declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			port_high = atoi(ptr);
			while ( *ptr && *ptr != ',' ) ptr++;
			if ( *ptr != ',' ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-low declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			ptr++;
			port_low = atoi(ptr);
			sprintf(data_ip,"%d.%d.%d.%d",a,b,c,d);
			data_socky.sin_family = AF_INET;
			data_socky.sin_addr.s_addr = inet_addr(data_ip);
			data_port = port_low + port_high * 256;
			data_socky.sin_port = htons((short)data_port);
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) Data-Connection: [%s:%d]\n",inet_ntoa(socky.sin_addr),FTP_PORT,data_ip,data_port);
#endif
			data_sock = socket(AF_INET,SOCK_STREAM,0);
			if ( data_sock < 0 ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting cannot create socket for passive-transfer\n",inet_ntoa(socky.sin_addr),FTP_PORT);
				return(-1);
			}
			if ( connect(data_sock,(struct sockaddr *)&data_socky,sizeof(data_socky)) < 0 ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot connect to data-socket at (%s:%d)\n",inet_ntoa(socky.sin_addr),FTP_PORT,data_ip,data_port);
				return(-1);
			}
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) DATA-SOCKET connected to: [%s:%d]\n",inet_ntoa(socky.sin_addr),FTP_PORT,data_ip,data_port);
#endif
		}
		if ( strlen(wildcard2) ){
			sprintf(buf,"IUPD %s %s %s\r\n",remote_file,wildcard1,wildcard2);
		} else {
			sprintf(buf,"IUPD %s %s\r\n",remote_file,wildcard1);
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		ftp_write_bytes(sock,NULL,buf,strlen(buf));
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif

		if ( response_code != 150 ){
			close(sock);
			close(data_sock);
			return(-1);
		}
		{ 
			int c;
			fp = fopen(local_file,"r");
			if ( fp != NULL ){
				while ( (c = fgetc(fp)) != -1 ){
					char x;
					x = (char) c;	
					ftp_write_bytes(data_sock,NULL,&x,1);
				}
				fclose(fp);
			}
			
		}
		close(data_sock);
		
		
		
	}		
	sprintf(buf,"QUIT\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	close(sock);
	return(0);	
		
}

int ftp_mtransfer(char *server, char *user, char *pwd, char *local_file, char *remote_file, int direction){
	int sock;
	struct sockaddr_in socky;
	struct hostent *hp;
	char buf[1024];
	int response_code;
	int data_sock;
	int data_port;
	char data_ip[128];
	struct sockaddr_in data_socky;
	struct stat st;





	ftp_logger("FTP(%s) (User: [%s], Pass: [%s]) Local-File: [%s], Remote-File: [%s], Mode: [%s]\n",
		server,user,pwd,local_file,remote_file, (direction == FTP_TRANSFER_SEND) ? "PUT" : "GET");

	if ( stat(local_file,&st) ){
		if (  mkdir(local_file,00777) ){
			ftp_logger("FTP(%s) Cannot create/stat '%s'\n",server,local_file);
			return(-3);
		}
	} else {
		if ( !S_ISDIR(st.st_mode) ){
			ftp_logger("FTP(%s) '%s' is not a directory\n",server,local_file);
			return(-3);
		}
	}

	socky.sin_port = htons(FTP_PORT);
	socky.sin_family = AF_INET;
	if ( inet_addr(server) == INADDR_NONE ){
		hp = gethostbyname(server);
		if ( hp == NULL ){
			ftp_logger("FTP(%s:%d) Cannot resolve hostname '%s'\n",__FILE__,__LINE__,server);
			return(-1);
		}
		socky.sin_addr = *((struct in_addr *)hp->h_addr);
	} else {
		socky.sin_addr.s_addr = inet_addr(server);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connecting to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	sock = socket(AF_INET,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("(%s:%d) Cannot create socket!\n",__FILE__,__LINE__);
		return(-2);
	}
	if ( connect(sock,(struct sockaddr *)&socky,sizeof(socky)) < 0  ){
		ftp_logger("(%s:%d) Cannot connect socket!\n",__FILE__,__LINE__);
		return(-2);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connected to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}

#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif


	sprintf(buf,"USER %s\r\n",user);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	sprintf(buf,"PASS %s\r\n",pwd);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 230 ){
		close(sock);
		ftp_logger("FTP(%s:%d) LOGIN FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}

	sprintf(buf,"TYPE I\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 250 ){
		close(sock);
		ftp_logger("FTP(%s:%d) Setting binary-mode FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}
	sprintf(buf,"PASV\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 227 ){
		close(sock);
		ftp_logger("FTP(%s:%d) Setting passive-mode FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}
	{
		char *ptr;
		int a,b,c,d;
		int port_low;
		int port_high;

		ptr = buf;
		while ( *ptr && *ptr != '(' ) ptr++;
		if ( *ptr != '(' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-first-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
			return(-1);
		}
		ptr++;
		a = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-second-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
			return(-1);
		}
		ptr++;
		b = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-third-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
			return(-1);
		}
		ptr++;
		c = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-fourth-byte declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
			return(-1);
		}
		ptr++;
		d = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-high declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
			return(-1);
		}
		ptr++;
		port_high = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-low declared)!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
			return(-1);
		}
		ptr++;
		port_low = atoi(ptr);
		sprintf(data_ip,"%d.%d.%d.%d",a,b,c,d);
		data_socky.sin_family = AF_INET;
		data_socky.sin_addr.s_addr = inet_addr(data_ip);
		data_port = port_low + port_high * 256;
		data_socky.sin_port = htons((short)data_port);
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) Data-Connection: [%s:%d]\n",inet_ntoa(socky.sin_addr),FTP_PORT,data_ip,data_port);
#endif
		data_sock = socket(AF_INET,SOCK_STREAM,0);
		if ( data_sock < 0 ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting cannot create socket for passive-transfer\n",inet_ntoa(socky.sin_addr),FTP_PORT);
			return(-1);
		}
		if ( connect(data_sock,(struct sockaddr *)&data_socky,sizeof(data_socky)) < 0 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot connect to data-socket at (%s:%d)\n",inet_ntoa(socky.sin_addr),FTP_PORT,data_ip,data_port);
			return(-1);
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) DATA-SOCKET connected to: [%s:%d]\n",inet_ntoa(socky.sin_addr),FTP_PORT,data_ip,data_port);
#endif
	}

	if ( direction == FTP_TRANSFER_SEND ){
		DIR *dir;
		struct dirent *diry;
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) SEND-DIR: [%s] --> [%s]\n",inet_ntoa(socky.sin_addr),FTP_PORT,remote_file,local_file);
#endif

		dir = opendir(local_file);
		if ( dir == NULL ){
			ftp_logger("FTP(%s:%d): Cannot open '%s' for reading\n",__FILE__,__LINE__,local_file);
			close(data_sock);
			close(sock);
			return(-1);
		}
		sprintf(buf,"IDIP %s\r\n",remote_file); // Directory is not deleted
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		ftp_write_bytes(sock,NULL,buf,strlen(buf));
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
		if ( response_code != 150 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot retrieve data\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file);
			return(-1);
		}
		while ( (diry = readdir(dir)) != NULL ){
			uint32_t size;
			uint32_t siz;
			struct stat st;
			char fname[1024];
			char c;
			FILE *fp;
			int i;


			if ( strcmp(diry->d_name,".") == 0 ) continue;
			if ( strcmp(diry->d_name,"..") == 0 ) continue;
			sprintf(fname,"%s/%s",local_file,diry->d_name);
			if ( stat(fname,&st) != 0 || !S_ISREG(st.st_mode) ){
				ftp_logger("FTP(%s:%d) skipping [%s]\n",__FILE__,__LINE__,fname);
				continue;
			}
			if ( (fp = fopen(fname,"r")) == NULL ){
				ftp_logger("FTP(%s:%d) skipping [%s] (cannot open)\n",__FILE__,__LINE__,fname);
				continue;
			}
			siz = (uint32_t)htonl(strlen(diry->d_name));
			if ( ftp_write_bytes(data_sock,NULL,(void *)&siz,sizeof(siz)) != sizeof(siz) ){
				ftp_logger("Cannot send filename-size to FTP-Server\n");
				close(data_sock);
				close(sock);
				return(-1);
			}
			if ( ftp_write_bytes(data_sock,NULL,(void *)diry->d_name,strlen(diry->d_name)) != strlen(diry->d_name) ){
				ftp_logger("Cannot send filename to FTP-Server\n");
				close(data_sock);
				close(sock);
				return(-1);
			}
			siz = (uint32_t)htonl(st.st_size);
			if ( ftp_write_bytes(data_sock,NULL,(void *)&siz,sizeof(siz)) != sizeof(siz) ){
				ftp_logger("Cannot send file-size to FTP-Server\n");
				close(data_sock);
				close(sock);
				return(-1);
			}
			for ( i = 0; i < st.st_size; i++ ){
				c = fgetc(fp);
				if ( ftp_write_bytes(data_sock,NULL,(void *)&c,1) != 1 ){
					ftp_logger("Cannot send file-data to FTP-Server\n");
					close(data_sock);
					close(sock);
					return(-1);
				}
			}
			fclose(fp);	
		}
		closedir(dir);
		{	
			uint32_t siz;
			siz = (uint32_t) 0L;	
			if ( ftp_write_bytes(data_sock,NULL,(void *)&siz,sizeof(siz)) != sizeof(siz) ){
				ftp_logger("Cannot send 0-size to FTP-Server\n");
				close(data_sock);
				close(sock);
				return(-1);
			}
		}


		close(data_sock);
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) Sent: all files\n",inet_ntoa(socky.sin_addr),FTP_PORT);
#endif
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif

		if ( response_code != 226 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot retrieve data(no 226 response after transfer)\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file);
			return(-1);
		}
	} else {
		int bytes_in;
		int c;
		char fname[1024];
		uint32_t size;
		uint32_t siz;
		FILE *fp;
	
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RECEIVE-DIR: [%s] --> [%s]\n",inet_ntoa(socky.sin_addr),FTP_PORT,remote_file,local_file);
#endif
		sprintf(buf,"IDIR %s\r\n",remote_file);
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		ftp_write_bytes(sock,NULL,buf,strlen(buf));
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
		if ( response_code != 150 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot retrieve data\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file);
			return(-1);
		}
		while ( 1 ){
			char lname[1024];
			int i;
			if ( ftp_read_bytes(data_sock,NULL,(void *)&size,sizeof(size)) != sizeof(size) ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot retrieve data - communication-error (%s:%d)\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file,__FILE__,__LINE__);
				return(-1);
			}
			siz = ntohl(size);
			if ( siz == 0 ) break; // We are finished :-)
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) File-Name-Size: %d Size of UNSIGNED LONG: %d\n",__FILE__,__LINE__,siz,sizeof(size));
#endif
			if ( ftp_read_bytes(data_sock,NULL,(void *)lname,siz) != siz ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot retrieve data - communication-error (%s:%d)\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file,__FILE__,__LINE__);
				return(-1);
			}
			lname[siz] = '\0';
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) File-Name: [%s]\n",__FILE__,__LINE__,lname);
#endif
			sprintf(fname,"%s/%s",local_file,lname);
			unlink(fname);
			if ( ftp_read_bytes(data_sock,NULL,(void *)&size,sizeof(size)) != sizeof(size) ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot retrieve data - communication-error (%s:%d)\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file,__FILE__,__LINE__);
				return(-1);
			}
			siz = ntohl(size);
			if ( siz == 0 ) break; // We are finished :-)
			ftp_logger("FTP(%s:%d) File-Size: %d\n",__FILE__,__LINE__,siz);
			fp = fopen(fname,"w");	
			if ( fp == NULL ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot retrieve data - communication-error (%s:%d)\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file,__FILE__,__LINE__);
				return(-1);
			}
			for ( i = 0; i < siz; i++ ){
				char c;
				if ( ftp_read_bytes(data_sock,NULL,(void *)&c,1) != 1 ){
					close(data_sock);
					close(sock);
					ftp_logger("FTP(%s:%d) Cannot retrieve data - communication-error (%s:%d)\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file,__FILE__,__LINE__);
					return(-1);
				}	
				fputc(c,fp);
			}
			fclose(fp);	
		}
		/*
		bytes_in = 0;
		while ( ftp_read_bytes(data_sock,NULL,(char *)&c,1) == 1 ){
			bytes_in++;
			fputc(c,fp);
		}
		*/
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) Received: %d Bytes\n",inet_ntoa(socky.sin_addr),FTP_PORT,bytes_in);
#endif
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif

		if ( response_code != 226 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot retrieve data(no 226 response after transfer)\n",inet_ntoa(socky.sin_addr),FTP_PORT,local_file);
			return(-1);
		}
			
	}

	sprintf(buf,"QUIT\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	close(sock);
	return(0);	
		
}
int ftp_delete(char *server, char *user, char *pwd, char *cmd){
	int sock;
	struct sockaddr_in socky;
	struct hostent *hp;
	int response_code;
	char buf[1024];

	ftp_logger("FTP(%s) (User: [%s], Pass: [%s]) CMD: [%s]\n", server,user,pwd,cmd);

	socky.sin_port = htons(FTP_PORT);
	socky.sin_family = AF_INET;
	if ( inet_addr(server) == INADDR_NONE ){
		hp = gethostbyname(server);
		if ( hp == NULL ){
			ftp_logger("FTP(%s:%d) Cannot resolve hostname '%s'\n",__FILE__,__LINE__,server);
			return(-1);
		}
		socky.sin_addr = *((struct in_addr *)hp->h_addr);
	} else {
		socky.sin_addr.s_addr = inet_addr(server);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connecting to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	sock = socket(AF_INET,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("(%s:%d) Cannot create socket!\n",__FILE__,__LINE__);
		return(-2);
	}
	if ( connect(sock,(struct sockaddr *)&socky,sizeof(socky)) < 0  ){
		ftp_logger("(%s:%d) Cannot connect socket!\n",__FILE__,__LINE__);
		return(-2);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connected to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}

#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif


	sprintf(buf,"USER %s\r\n",user);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	sprintf(buf,"PASS %s\r\n",pwd);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 230 ){
		close(sock);
		ftp_logger("FTP(%s:%d) LOGIN FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}
	sprintf(buf,"DELE %s\r\n",cmd);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 250 ){
		close(sock);
		ftp_logger("FTP(%s:%d) LOGIN FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}
	sprintf(buf,"QUIT\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	close(sock);
	return(0);	
}

int ftp_iexe(char *server, char *user, char *pwd, char *cmd){
	int sock;
	struct sockaddr_in socky;
	struct hostent *hp;
	int response_code;
	char buf[1024];

	ftp_logger("FTP(%s) (User: [%s], Pass: [%s]) CMD: [%s]\n", server,user,pwd,cmd);

	socky.sin_port = htons(FTP_PORT);
	socky.sin_family = AF_INET;
	if ( inet_addr(server) == INADDR_NONE ){
		hp = gethostbyname(server);
		if ( hp == NULL ){
			ftp_logger("FTP(%s:%d) Cannot resolve hostname '%s'\n",__FILE__,__LINE__,server);
			return(-1);
		}
		socky.sin_addr = *((struct in_addr *)hp->h_addr);
	} else {
		socky.sin_addr.s_addr = inet_addr(server);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connecting to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	sock = socket(AF_INET,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("(%s:%d) Cannot create socket!\n",__FILE__,__LINE__);
		return(-2);
	}
	if ( connect(sock,(struct sockaddr *)&socky,sizeof(socky)) < 0  ){
		ftp_logger("(%s:%d) Cannot connect socket!\n",__FILE__,__LINE__);
		return(-2);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connected to '%s:%d'\n",__FILE__,__LINE__,inet_ntoa(socky.sin_addr),FTP_PORT);
#endif

	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}

#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif


	sprintf(buf,"USER %s\r\n",user);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	sprintf(buf,"PASS %s\r\n",pwd);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 230 ){
		close(sock);
		ftp_logger("FTP(%s:%d) LOGIN FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}
	sprintf(buf,"IEXE %s\r\n",cmd);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	if ( response_code != 250 ){
		close(sock);
		ftp_logger("FTP(%s:%d) LOGIN FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}
	sprintf(buf,"QUIT\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",inet_ntoa(socky.sin_addr),FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",inet_ntoa(socky.sin_addr),FTP_PORT,response_code);
#endif
	close(sock);
	return(0);	
}

int ftp_transfer(char *server, char *user, char *pwd, char *local_file, char *remote_file, int direction){
	int sock;
	struct sockaddr_in socky;
	struct hostent *hp;
	char buf[1024];
	int response_code;
	int data_sock;
	int data_port;
	char data_ip[1280];
	struct sockaddr_in data_socky;
	struct sockaddr *sockaddr;
	int sock_addr_len;
	int sock_addr_family;
	char printable[1024];



	ftp_logger("FTP(%s) (User: [%s], Pass: [%s]) Local-File: [%s], Remote-File: [%s], Mode: [%s]\n",
		server,user,pwd,local_file,remote_file, (direction == FTP_TRANSFER_SEND) ? "PUT" : "GET");

	if ( get_sockaddr(AF_UNSPEC,SOCK_STREAM,server,FTP_PORT,&sockaddr,&sock_addr_family,&sock_addr_len,printable,1024) ){
		ftp_logger("FTP(%s) Cannot get address\n",server);
		return(-1);
	}

#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connecting to '%s:%d'\n",__FILE__,__LINE__,printable,FTP_PORT);
#endif

	sock = socket(sock_addr_family,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("(%s:%d) Cannot create socket!\n",__FILE__,__LINE__);
		return(-2);
	}
	if ( connect(sock,(struct sockaddr *)sockaddr,(sock_addr_len)) < 0  ){
		ftp_logger("(%s:%d) Cannot connect socket!\n",__FILE__,__LINE__);
		return(-2);
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) Connected to '%s:%d'\n",__FILE__,__LINE__,printable,FTP_PORT);
#endif

	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}

#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif


	sprintf(buf,"USER %s\r\n",user);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
	sprintf(buf,"PASS %s\r\n",pwd);
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
	if ( response_code != 230 ){
		close(sock);
		ftp_logger("FTP(%s:%d) LOGIN FAILED!\n",printable,FTP_PORT);
		return(-1);
	}

	sprintf(buf,"TYPE I\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
	if ( response_code != 250 ){
		close(sock);
		ftp_logger("FTP(%s:%d) Setting binary-mode FAILED!\n",printable,FTP_PORT);
		return(-1);
	}
	if ( sock_addr_family == AF_INET6 ){
		sprintf(buf,"EPSV\r\n");
	} else {
		sprintf(buf,"PASV\r\n");
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
	if ( response_code != 227 && response_code != 229 ){
		close(sock);
		ftp_logger("FTP(%s:%d) Setting passive-mode FAILED!\n",inet_ntoa(socky.sin_addr),FTP_PORT);
		return(-1);
	}
	if ( sock_addr_family == AF_INET6 ){
			struct sockaddr *addr_data;
			int data_family;
			int data_addr_len;
			char *ptr;
			ptr = buf;
			while ( *ptr && *ptr != '|' ) ptr++;
			if ( *ptr != '|' ) {
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No passive-connection declared)!\n",printable,FTP_PORT);
				return(-1);
			}
			while ( *ptr && !isdigit(*ptr) ) ptr++;
			if ( !isdigit(*ptr) ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Port declared)!\n",printable,FTP_PORT);
				return(-1);
			}	
			data_port = atoi(ptr);
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) Remote-Port: [%d]\n",printable,FTP_PORT,data_port);
#endif
			if ( get_sockaddr(AF_INET6,SOCK_STREAM,server,data_port,&addr_data,&data_family,&data_addr_len,data_ip,1024) ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Addr available)!\n",printable,FTP_PORT);
				return(-1);
			}
			data_sock = socket(data_family,SOCK_STREAM,0);
			if ( data_sock < 0 ){
				close(sock);
				ftp_logger("FTP(%s:%d) Setting cannot create socket for passive-transfer\n",printable,FTP_PORT);
				return(-1);
			}
			if ( connect(data_sock,(struct sockaddr *)addr_data,data_addr_len) < 0 ){
				close(data_sock);
				close(sock);
				ftp_logger("FTP(%s:%d) Cannot connect to data-socket at (%s:%d)\n",printable,FTP_PORT,data_ip,data_port);
				return(-1);
			}
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) DATA-SOCKET connected to: [%s:%d]\n",printable,FTP_PORT,data_ip,data_port);
#endif

	}
	if ( sock_addr_family == AF_INET ) {
		char *ptr;
		int a,b,c,d;
		int port_low;
		int port_high;

		ptr = buf;
		while ( *ptr && *ptr != '(' ) ptr++;
		if ( *ptr != '(' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-first-byte declared)!\n",printable,FTP_PORT);
			return(-1);
		}
		ptr++;
		a = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-second-byte declared)!\n",printable,FTP_PORT);
			return(-1);
		}
		ptr++;
		b = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-third-byte declared)!\n",printable,FTP_PORT);
			return(-1);
		}
		ptr++;
		c = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-fourth-byte declared)!\n",printable,FTP_PORT);
			return(-1);
		}
		ptr++;
		d = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-high declared)!\n",printable,FTP_PORT);
			return(-1);
		}
		ptr++;
		port_high = atoi(ptr);
		while ( *ptr && *ptr != ',' ) ptr++;
		if ( *ptr != ',' ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting passive-mode FAILED (No Host-port-low declared)!\n",printable,FTP_PORT);
			return(-1);
		}
		ptr++;
		port_low = atoi(ptr);
		sprintf(data_ip,"%d.%d.%d.%d",a,b,c,d);
		data_socky.sin_family = AF_INET;
		data_socky.sin_addr.s_addr = inet_addr(data_ip);
		data_port = port_low + port_high * 256;
		data_socky.sin_port = htons((short)data_port);
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) Data-Connection: [%s:%d]\n",printable,FTP_PORT,data_ip,data_port);
#endif
		data_sock = socket(AF_INET,SOCK_STREAM,0);
		if ( data_sock < 0 ){
			close(sock);
			ftp_logger("FTP(%s:%d) Setting cannot create socket for passive-transfer\n",printable,FTP_PORT);
			return(-1);
		}
		if ( connect(data_sock,(struct sockaddr *)&data_socky,sizeof(data_socky)) < 0 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot connect to data-socket at (%s:%d)\n",printable,FTP_PORT,data_ip,data_port);
			return(-1);
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) DATA-SOCKET connected to: [%s:%d]\n",printable,FTP_PORT,data_ip,data_port);
#endif
	}

	if ( direction == FTP_TRANSFER_SEND ){
		int bytes_out;
		int c;
		FILE *fp;
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) SEND-FILE: [%s] --> [%s]\n",printable,FTP_PORT,local_file,remote_file);
#endif
		fp = fopen(local_file,"r");
		if ( fp == NULL ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) [%s: %d] Cannot open local-file for reading [%s]\n",printable,FTP_PORT,__FILE__,__LINE__,local_file);
			return(-1);
		}	
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) SEND-FILE: [%s] --> [%s]\n",printable,FTP_PORT,local_file,remote_file);
#endif
		sprintf(buf,"STOR %s\r\n",remote_file);
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
		ftp_write_bytes(sock,NULL,buf,strlen(buf));
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
		if ( response_code != 150 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot retrieve data\n",printable,FTP_PORT,local_file);
			return(-1);
		}
		bytes_out = 0;
		while ( (c = fgetc(fp)) != -1 ){
			bytes_out++;
			ftp_write_bytes(data_sock,NULL,(char *)&c,1);
		}
		fclose(fp);
		close(data_sock);
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) Sent: %d Bytes\n",printable,FTP_PORT,bytes_out);
#endif
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif

		if ( response_code != 226 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot retrieve data(no 226 response after transfer)\n",printable,FTP_PORT,local_file);
			return(-1);
		}
	} else {
		int bytes_in;
		int c;
		FILE *fp;
		unlink(local_file);
		fp = fopen(local_file,"w");
		if ( fp == NULL ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) [%s:%d] Cannot open local-file for writing\n",printable,FTP_PORT,__FILE__,__LINE__,local_file);
			return(-1);
		}	
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RECEIVE-FILE: [%s] --> [%s]\n",printable,FTP_PORT,remote_file,local_file);
#endif
		sprintf(buf,"RETR %s\r\n",remote_file);
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
		ftp_write_bytes(sock,NULL,buf,strlen(buf));
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
		if ( response_code != 150 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot retrieve data\n",printable,FTP_PORT,local_file);
			return(-1);
		}
		bytes_in = 0;
		while ( ftp_read_bytes(data_sock,NULL,(char *)&c,1) == 1 ){
			bytes_in++;
			fputc(c,fp);
		}
		fclose(fp);
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) Received: %d Bytes\n",printable,FTP_PORT,bytes_in);
#endif
		while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
			ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
			if ( (response_code = ftp_response_code(buf)) != -1 ){
				break;
			}
		}
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif

		if ( response_code != 226 ){
			close(data_sock);
			close(sock);
			ftp_logger("FTP(%s:%d) Cannot retrieve data(no 226 response after transfer)\n",printable,FTP_PORT,local_file);
			return(-1);
		}
			
	}

	sprintf(buf,"QUIT\r\n");
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) >> %s",printable,FTP_PORT,buf);
#endif
	ftp_write_bytes(sock,NULL,buf,strlen(buf));
	while ( ftp_read_line(sock,NULL,buf,1024) != -1 ){
#ifdef FTP_DEBUG
		ftp_logger("FTP(%s:%d) << %s",printable,FTP_PORT,buf);
#endif
		if ( (response_code = ftp_response_code(buf)) != -1 ){
			break;
		}
	}
#ifdef FTP_DEBUG
	ftp_logger("FTP(%s:%d) RESPONSE-Code: %d\n",printable,FTP_PORT,response_code);
#endif
	close(sock);
	return(0);	
		
}

















char *_send_ftp_raw_cmd2_l(char *server, char *user, char *pwd, char *cmd, char *cmd2, char *file, int line){
	char *reply;
	int sock;
	FILE *in;
	FILE *out;
	char buf[1024];
	char *ptr;
	struct sockaddr_in socky;
	struct hostent *hp;

	if ( inet_addr(server) == INADDR_NONE ){
		hp = gethostbyname(server);
		if ( hp == NULL ){
			ftp_logger("RAW_FTP_COMMAND(%s:%d) cannot resolve [%s]\n",file,line,server);
			return(NULL);
		}
		bcopy((void *)hp->h_addr,(void *)&socky.sin_addr,hp->h_length);
	} else {
		socky.sin_addr.s_addr = inet_addr(server);
	}
	socky.sin_family = AF_INET;
	socky.sin_port   = htons(21);
	
	sock = socket(AF_INET,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("RAW_FTP_COMMAND(%s:%d) cannot create socket\n",file,line);
		return(NULL);
	}
	if ( connect(sock,(struct sockaddr *)&socky,sizeof(socky)) < 0 ){
		close(sock);
		ftp_logger("RAW_FTP_COMMAND(%s:%d) cannot connect socket\n",file,line);
		return(NULL);
	}
	in  = fdopen(sock,"r");
	out = fdopen(sock,"w");

	// Get greeting
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No greeting received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	sprintf(buf,"USER %s",user);
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,buf);
	fprintf(out,"%s\n",buf); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	sprintf(buf,"PASS %s",pwd);
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,buf);
	fprintf(out,"%s\n",buf); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,cmd);
	fprintf(out,"%s\n",cmd); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,cmd2);
	fprintf(out,"%s\n",cmd2); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	reply = strdup(buf);
	sprintf(buf,"QUIT");
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,buf);
	fprintf(out,"%s\n",buf); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	fclose(in);
	fclose(out);
	close(sock);
	return(strdup(reply));
	
}

char *_send_ftp_raw_cmd_l(char *server, char *user, char *pwd, char *cmd, char *file, int line){
	char *reply;
	int sock;
	FILE *in;
	FILE *out;
	char buf[1024];
	char *ptr;
	struct sockaddr_in socky;
	struct hostent *hp;

	if ( inet_addr(server) == INADDR_NONE ){
		hp = gethostbyname(server);
		if ( hp == NULL ){
			ftp_logger("RAW_FTP_COMMAND(%s:%d) cannot resolve [%s]\n",file,line,server);
			return(NULL);
		}
		bcopy((void *)hp->h_addr,(void *)&socky.sin_addr,hp->h_length);
	} else {
		socky.sin_addr.s_addr = inet_addr(server);
	}
	socky.sin_family = AF_INET;
	socky.sin_port   = htons(21);
	
	sock = socket(AF_INET,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("RAW_FTP_COMMAND(%s:%d) cannot create socket\n",file,line);
		return(NULL);
	}
	if ( connect(sock,(struct sockaddr *)&socky,sizeof(socky)) < 0 ){
		close(sock);
		ftp_logger("RAW_FTP_COMMAND(%s:%d) cannot connect socket\n",file,line);
		return(NULL);
	}
	in  = fdopen(sock,"r");
	out = fdopen(sock,"w");

	// Get greeting
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No greeting received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	sprintf(buf,"USER %s",user);
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,buf);
	fprintf(out,"%s\n",buf); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	sprintf(buf,"PASS %s",pwd);
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,buf);
	fprintf(out,"%s\n",buf); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,cmd);
	fprintf(out,"%s\n",cmd); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	reply = strdup(buf);
	sprintf(buf,"QUIT");
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,buf);
	fprintf(out,"%s\n",buf); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	fclose(in);
	fclose(out);
	close(sock);
	return(strdup(reply));
	
}


char *_send_ftp_raw_cmd(char *server, char *cmd, char *file, int line){
	char *reply;
	int sock;
	FILE *in;
	FILE *out;
	char buf[1024];
	char *ptr;
	struct sockaddr_in socky;
	struct hostent *hp;

	if ( inet_addr(server) == INADDR_NONE ){
		hp = gethostbyname(server);
		if ( hp == NULL ){
			ftp_logger("RAW_FTP_COMMAND(%s:%d) cannot resolve [%s]\n",file,line,server);
			return(NULL);
		}
		bcopy((void *)hp->h_addr,(void *)&socky.sin_addr,hp->h_length);
	} else {
		socky.sin_addr.s_addr = inet_addr(server);
	}
	socky.sin_family = AF_INET;
	socky.sin_port   = htons(21);
	
	sock = socket(AF_INET,SOCK_STREAM,0);
	if ( sock < 0 ){
		ftp_logger("RAW_FTP_COMMAND(%s:%d) cannot create socket\n",file,line);
		return(NULL);
	}
	if ( connect(sock,(struct sockaddr *)&socky,sizeof(socky)) < 0 ){
		close(sock);
		ftp_logger("RAW_FTP_COMMAND(%s:%d) cannot connect socket\n",file,line);
		return(NULL);
	}
	in  = fdopen(sock,"r");
	out = fdopen(sock,"w");

	// Get greeting
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No greeting received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	sprintf(buf,"USER root");
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,buf);
	fprintf(out,"%s\n",buf); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	sprintf(buf,"PASS AudiA4quattro");
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,buf);
	fprintf(out,"%s\n",buf); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,cmd);
	fprintf(out,"%s\n",cmd); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	reply = strdup(buf);
	sprintf(buf,"QUIT");
	ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] >> [%s]\n",file,line,buf);
	fprintf(out,"%s\n",buf); fflush(out);
	while ( (ptr = fgets(buf,1024,in)) != NULL ){
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		if ( buf[strlen(buf)-1] == '\r' || buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0';
		ftp_logger("RAW_FTP_COMMAND[%s:%d,DEBUG] << [%s]\n",file,line,buf);
		if ( buf[3] != '-' ) break;
	}
	if ( ptr == NULL ){
		ftp_logger("RAW_FTP_COMMAND[%s:%d,FATAL] << [No answer received]\n",file,line);
		fclose(in);
		fclose(out);
		close(sock);
		return(NULL);
	}
	fclose(in);
	fclose(out);
	close(sock);
	return(strdup(reply));
	
}


char *make_print(unsigned char *in,int len){
	static char retval[2048];
	int i;
	bzero(retval,2048);
	for ( i = 0; i < len; i++ ){
		if ( isalnum(in[i]) || isblank(in[i]) || in[i] == ':' || in[i] == ';' || in[i] == ',' || in[i] == '?' || in[i] == '!' || in[i] == '.' || in[i] == '_' || in[i] == '/' || in[i] == '\\' || in[i] == '(' || in[i] == ')' || in[i] == '[' || in[i] == ']' || in[i] == '{' || in[i] == '}' || in[i] == '\"' || in[i] == '\'' || in[i] == '-' ){
			sprintf(&retval[strlen(retval)],"%c",in[i]);
		} else {
			sprintf(&retval[strlen(retval)],"\\0x%02X",(unsigned int) in[i]);
		}
		if ( i >= 30 ){
			sprintf(&retval[strlen(retval)],"...");
			break; 
		}
	}
	return(retval);
}

char *make_json_print(unsigned char *in, int len){
	static char retval[2048];
	int i;
	bzero(retval,2048);
	for ( i = 0; i < len; i++ ){
		if ( isalnum(in[i]) || isblank(in[i]) || in[i] == ':' || in[i] == ';' || in[i] == ',' || in[i] == '?' || in[i] == '!' || in[i] == '.' || in[i] == '_' || in[i] == '/' || in[i] == '\\' || in[i] == '(' || in[i] == ')' || in[i] == '[' || in[i] == ']' || in[i] == '{' || in[i] == '}' || in[i] == '\'' || in[i] == '-' ){
			sprintf(&retval[strlen(retval)],"%c",in[i]);
		} else {
			sprintf(&retval[strlen(retval)],"[0x%02X]",(unsigned int) in[i]);
		}
		if ( i >= 30 ){
			sprintf(&retval[strlen(retval)],"...");
			break; 
		}
	}
	return(retval);
}


