/***************************************************************************
 *   Copyright (C) 2004 by Johnny Mast                                     *
 *   rave@rosiello.org                                                     *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
//#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/mman.h>


 /* used for open() */
#include <sys/stat.h>
#include <fcntl.h>

#include <stdio.h>
 
#include <ls.h>
#include <ftpd_core.h>

#define DEBUG

int  start_ftpd(void);
int  data_con(const char *data,int port,char *host, int type,struct connection *client,int extra);
int  idata_con(int port,char *file,char c_type,int type ,int sock);
int  send_data(char *data,int socket);
char *net_resolve(const char *host) ;



int start_ftpd(void)
{
struct sockaddr_in serv_addr;
struct sockaddr_in client_info;
struct connection *conn;
fd_set listen_set,org_set;
int sock, selector = getdtablesize();
int ret,slen,sc;
pid_t pid;
char data[MAX_READ];

   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(1101);

   
  sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (!sock) 
   { perror ("socket() error\n");
     return -1;
   }
   
   int trueval=1;
   setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&trueval,sizeof(trueval));
   
   
   if(bind(sock,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) {
    perror("error_bind");
    return -1;
   }
   
   listen (sock  , 5) ;
   
   FD_ZERO(&org_set);
   FD_SET (sock, &org_set);
        
   while (1) 
  {
    bcopy (&org_set,&listen_set,sizeof(org_set));
   
    //FD_ZERO(&listen_set);
 
   
   
   
   ret = select(selector+1, &listen_set, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
   if(ret >0 )
   {
     if(FD_ISSET(sock,&listen_set)==1)
     {
   
     /* you got a new connection */
      /* do something */
     
     slen = sizeof(struct sockaddr_in);
     if ((sc=accept(sock,(struct sockaddr_in *)&client_info, &slen)) == -1) 
      perror ("Accept");
     
     /* Add this new connection to the FD set to allow data read from it. */
     printf("adding socket %d\n",sc);
     FD_SET(sc, &org_set);
     send_data(status(220),sc);
     
     /* Whe need to add this New connection to our connection 
        Data Base. Why ? its to store connection information */
	
	add_client ( (struct sockaddr_in *)&client_info,(struct sockaddr_in *)&serv_addr, sc );
         
           
     }
     
     conn = start;
     while (conn)
     {
     
      if(FD_ISSET(conn ->fd,&listen_set)) 
       {

       
      
      memset(data,'\0',sizeof(data));
      strcpy(data , strip_nl(get_data(conn)));
      printf("data = >%s<",data);
      if (  handleuser(conn,&data)  > 0) {
       R_CON(conn);
       FD_CLR  ( conn ->fd, &org_set ); 
       printf("session id %d timedout\n",conn->usr_rel.ses_id);
       close (conn->fd);
       }
   //   } 

     
       break;
       }
     
     
   //  fprintf(stderr,"conn->fd =%d\n",conn->fd);
     conn = conn ->next;
     
     }
     
     
     } // end ret ==
     
     
     
   } // end while
}






int send_data(char *data,int socket)
{

int count = strlen(data);


if ((write (socket, data, count)) == -1) return FAIL;

return OK;
}


char buffer[MAX_READ];
char *get_data(struct connection *conn)
{
int numbytes;

memset(buffer,'\0',MAX_READ);



while ( numbytes=read (conn->fd,buffer,MAX_READ) <= 0 ) 
buffer[numbytes]='\0';
return (char *)buffer;


// read (conn->fd,buffer,MAX_READ);
//printf("shared is %d and data = %s\n",shared,buffer);
///if (shared == 1) { shared =0; printf("timed out\n"); return (char *)-1;}



} 

int numbytes;
int data_con(const char *data,int port,char *host, int type, struct connection *client,int extra)
{
struct sockaddr_in client_addr;
char *content;
size_t size;
int sock,inc=0;
char *stor;
char buffer[512];
int ret,fin;

#ifdef DEBUG
  printf("host = %s\nport = %d\n",host,port);
#endif  
  client_addr.sin_family = AF_INET;
  client_addr.sin_addr.s_addr = inet_addr(host);
  client_addr.sin_port = htons(port);

  sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (!sock) 
   { perror ("socket() error\n");
     return FAIL;
   }
   
    if (connect (sock,&client_addr,sizeof(struct sockaddr_in)) < 0) 
    {
    
    close (sock);
    return FAIL;
    }

  
if (type == FILE_T) {


if ((fin=open ( data ,  O_RDONLY)) == -1) {
#ifdef DEBUG  
  perror("open");
#endif
  return -1;
}
numbytes =0; inc =0;
while ( ((inc = read (fin, buffer,sizeof(buffer)-1)) != 0) ) 
{
write (sock,buffer,numbytes);
numbytes +=inc;
memset(buffer,'\0',sizeof(buffer));
}

close (fin);
close (sock);
return numbytes;

} else if (type == STORFILE) {





if ((fin=open ( data ,  O_WRONLY | O_CREAT | O_TRUNC ,0644)) == -1) {
#ifdef DEBUG  
  perror("open");
#endif
  return -1;
 }

numbytes=0;inc = 0;
while ( (inc = read(sock,buffer,sizeof(buffer)-1))  !=0 )
{
numbytes +=strlen(strip_nl(buffer));
write (fin,buffer,numbytes);
memset(buffer,'\0',sizeof(buffer));
;
}
close (fin);
close (sock);


//printf ("numb = %d\n",numbytes);
return numbytes;
} else if ( type == APPEFILE ) {


if ((fin=open ( data ,  O_WRONLY | O_CREAT | O_APPEND ,0644)) == -1) {
#ifdef DEBUG  
  perror("open");
#endif
  return -1;
 }

lseek(fin,0,SEEK_END);
#ifdef DEBUG  
  perror("lseek");
#endif

numbytes=0;inc = 0;
int o=0;
while ( (inc = read(sock,buffer,sizeof(buffer)-1))  !=0 )
{
numbytes +=strlen(strip_nl(buffer));
for (o=0;o <strlen(buffer);++o) printf(" .%c. ",buffer[o]);
write (fin,buffer,numbytes);
memset(buffer,'\0',sizeof(buffer));
;
}
close (fin);
close (sock);




return numbytes;
} else {



//printf("data voor %s",data);
if ((dirlist(data,extra,send_data,sock)) == NULL)
 {  
 //close (sock);send_data(status(502),client->fd); return FAIL; 
 }

 printf("connection closed\n");
 close (sock);
 return OK;
}

}

/* On inalizing (INIT) the of server side listening data port sock will be returned to the calling function 
 * if sock is not -1 the server is successfully listening on the port thats aligned by the port variable.
 *
 * On transfer mode (wen STORS/STRU has been recved) (TRANSFER) the function needs the variableds file  
 * c_type (connection type) and sock to be set.
*/

int idata_con(int port,char *file,char c_type,int type ,int socks)
{


struct sockaddr_in serv_addr;
int ret,slen,sc;
pid_t pid;
char buffer[512];
int k;
char *file;
int soc;

if (type == INIT ) {
   serv_addr.sin_family = AF_INET;
   serv_addr.sin_addr.s_addr = INADDR_ANY;
   serv_addr.sin_port = htons(port);

   
  soc=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
   if (!soc) 
   { perror ("socket() error\n");
     return -1;
   }
   
   
   
   if(bind(soc,(struct sockaddr *)&serv_addr,sizeof(serv_addr)) < 0) {
    perror ("bind error ->>\n");
    return -1;
   }
   
  
   
   return soc;
} else {
   listen (socks  , 1) ;
   sc = accept(socks,0,0);
   
   printf("server accepted incomming call\nsc=%d",sc);
   printf("we maken %s aan\n",file);
    memset(buffer,'\0',sizeof(buffer));
   
//    file = writefile(file,99999);
   while (k=read (sc,buffer,sizeof(buffer)-1)  !=0)
   {
  // printf("buffer = %s\n",buffer);
     file=buffer;
     memset(buffer,'\0',sizeof(buffer));
   
   }

   close (sc);
   close (socket);

}



}



char *adres;
char *net_resolve(const char *host) 
{
struct hostent *hp;
struct sockaddr_in *sock;
unsigned int addr;



addr = inet_addr ((char *)host);
hp = ISIP(host) ?  
	(struct hostent *)gethostbyaddr((char *)&addr,4,AF_INET) :
	(struct hostent *)gethostbyname(host) ;
	
	 


if (!hp ) return NULL;

memcpy(&sock->sin_addr,hp->h_addr,hp->h_length);
adres = strdup(inet_ntoa(sock->sin_addr));
return (char *)adres;


 


}
