Exemplo n.º 1
0
Arquivo: handles.c Projeto: yuyuvn/ftp
/**
 * Generates response message for client
 * @param cmd Current command
 * @param state Current connection state
 */
void response(Command *cmd, State *state)
{
  switch(lookup_cmd(cmd->command)){
    case USER: ftp_user(cmd,state); break;
    case PASS: ftp_pass(cmd,state); break;
    case PASV: ftp_pasv(cmd,state); break;
    case LIST: ftp_list(cmd,state); break;
    case CWD:  ftp_cwd(cmd,state); break;
    case PWD:  ftp_pwd(cmd,state); break;
    case MKD:  ftp_mkd(cmd,state); break;
    case RMD:  ftp_rmd(cmd,state); break;
    case RETR: ftp_retr(cmd,state); break;
    case STOR: ftp_stor(cmd,state); break;
    case DELE: ftp_dele(cmd,state); break;
    case SIZE: ftp_size(cmd,state); break;
    case ABOR: ftp_abor(state); break;
    case QUIT: ftp_quit(state); break;
    case TYPE: ftp_type(cmd,state); break;
    case CDUP: ftp_cdup(state); break;
    case HELP: ftp_help(cmd, state); break;
    case NLST: ftp_nlst(cmd, state); break;
    case RNFR: ftp_rnfr(cmd, state); break;
    case RNTO: ftp_rnto(cmd, state); break;
    case APPE: ftp_appe(cmd, state); break;
    case NOOP:
      if(state->logged_in){
        state->message = "200 Zzz...\n";
      }else{
        state->message = "530 Please login with USER and PASS\n";
      }
      write_state(state);
      break;
    default: 
      state->message = "500 Unknown command\n";
      write_state(state);
      break;
  }
}
Exemplo n.º 2
0
//
//	Get a remote file, calling the update function after each block arrives
//	Returns the total bytes received.  
//	fi_errno MUST be checked for errors
//	Returns -2 for AmigaDos errors - Use IoErr() to report/handle them
//	Returns -3 for FTP server errors - Use the fi_reply and fi_iobuf fields to report/handle them
//	Returns -1 for rare unlikely errors - Could cause DisplayBeep() etc...
//	now uses IOBUFSIZE 
//
//	Update callback must specify 0xffffffff for total and length if REST fails
//	Update callback must specify 0xffffffff for unknown total
//	Update callback must specify 0 for length of final call
//
unsigned int get( struct ftp_info *info, int (*updatefn)(void *,unsigned int,unsigned int), void *updateinfo, char *remote_path, char *local_path, BOOL restart )
{
// Needed because socket library base is in our task's tc_userdata field
//struct opusftp_globals *ogp = info->fi_og;
unsigned int            total = 0xffffffff;	// Length of file
unsigned int            bytes = 0;		// Bytes received so far
APTR                    f;			// Output file
int                     ds;			// Data socket
int                     b;			// Byte count
int                     reply;			// FTP reply
fd_set                  rd, ex; 
ULONG                   flags;
struct timeval          timer = {0};
int                     display_bytes;
int                     done;

D(bug( "get() '%s' -> '%s'\n", remote_path, local_path ));

// Valid?
if	(!info)
	return 0;

// No abort/error yet
info->fi_aborted = 0;
info->fi_errno = 0;
info->fi_ioerr = 0;
*info->fi_serverr = 0;

// More validity
if	(!remote_path || !local_path)
	{
	info->fi_errno |= FTPERR_XFER_RARERR;
	return 0;
	}

// init counters etc
display_bytes = done = 0;

// open output file for writing
if	((f = OpenBuf( (char *)local_path, restart ? MODE_OLDFILE : MODE_NEWFILE, WBUFSIZE )))
	{
	// Resuming?  So find out where to resume from
	if	(restart)
		{
		SeekBuf( f, 0, OFFSET_END );
		bytes = SeekBuf( f, 0, OFFSET_CURRENT );
		}

	// get connected  - bytes is a market flag 0/x for RETR/REST
	if	((ds = dataconna( info, bytes, "RETR %s", remote_path )) < 0)
		{
		// Source (server error)?
		if	(ds == -2 || ds == -3)
			{
			info->fi_errno |= FTPERR_XFER_SRCERR;
			stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 );
			}
		else
			info->fi_errno |= FTPERR_XFER_RARERR;
		}
	else
		{
		char *p;

		// Reset bytes if REST failed
		if	(bytes && (info->fi_flags & FTP_NO_REST))
			{
			if	(updatefn)
				(*updatefn)( updateinfo, 0xffffffff, 0xffffffff );

			SeekBuf( f, 0, OFFSET_BEGINNING );
			bytes = 0;
			}

		// First update tells callback where we're starting from
		if	(updatefn)
			(*updatefn)( updateinfo, total, bytes );

		// Does the RETR reply contain the file length?
		if ((p = strstr( info->fi_iobuf, " bytes)" )))
			if	(isdigit(*--p))
				{
				while	(isdigit(*p--)) ;
				total = atoi(p+2);
				}

		// do the transfer

		FD_ZERO( &rd );
		FD_ZERO( &ex );

		// set network timeout for the select wait call
		set_timeout(info,&timer);

		// loop fetch tcp data and save it
		while	(!done)
			{
			// Note: these masks must be set before every call and
			// are all cleared by select wait. Examine the masks
			// afterwards to see what was set

			FD_SET( ds, &rd );
			FD_SET( ds, &ex );
			flags = SIGBREAKF_CTRL_D; 

			if	(WaitSelect( ds + 1 , &rd, NULL, &ex, &timer, &flags ) >= 0)
				{
				// Is there some data ready for us?
				if	(FD_ISSET( ds, &rd ))
					{
					// then get it and store it
					if	((b = recv( ds, info->fi_iobuf, IOBUFSIZE, 0 )))
						{
						// save data
						if	(WriteBuf( f, info->fi_iobuf, b ) == b)
							{
							bytes += b;
	
							// progress bar uprate
							display_bytes += b;

							if	(display_bytes >= UPDATE_BYTE_LIMIT)
								{
								if	(updatefn)
									(*updatefn)( updateinfo, total, display_bytes );

								display_bytes = 0;
								}
							}
						// Write Error
						else
							{
							info->fi_errno |= FTPERR_XFER_DSTERR;
							info->fi_ioerr = IoErr();
							info->fi_aborted = 1;
							ftp_abor( info );
							done = TRUE;
							}	
						}
					else
						done = TRUE;
					}

				// did we get a signal to abort?
				if	(!done && (flags & SIGBREAKF_CTRL_D))
					{
					D(bug( "*** get() CTRL-D SIGNAL ***\n" ));
					info->fi_abortsignals = 0;
					info->fi_aborted = 1;
					ftp_abor( info );	// NEEDED why not just close socket?
					done = TRUE;
					}

				// did we get an exception? Other end closed connection maybe
				if	(FD_ISSET( ds, &ex ))
					{
					D(bug("** get() socket exception\n"));

					// has been aborted from remote ?
					done = TRUE;
					}
				}
			else
				{
				// some socket error -ve a 0 == timeout
				D(bug( "** get() WaitSelect error\n" ));
				done = TRUE;
				}
			}

		// Final progress bar redraw at 100% (if it finished)
		if	(!info->fi_aborted && !info->fi_errno && updatefn)
			(*updatefn)( updateinfo, total, 0 );

		//D(bug( "--> close(%ld)\n", ds ));
		CloseSocket( ds );

#ifdef	DEBUG
//			if	(ui)
//			timeit( ui, bytes );
#endif

		// Get reply to socket closure  Can TIMEOUT
		reply = getreply( info );

		// If transfer was aborted, read the ABOR reply (426)
		// (This could get the reply to RETR (226) but it don't matter)
		if	(info->fi_aborted && reply != 421)
			reply = getreply( info );

		// RETR successful? - Don't set error if we forced it!
		// (This could get the reply to ABOR (225) but it don't matter)
		if	(reply / 100 != COMPLETE)
			if	(!info->fi_errno)
				{
				info->fi_errno |= FTPERR_XFER_SRCERR;
				stccpy( info->fi_serverr, info->fi_iobuf, IOBUFSIZE + 1 );
				}
		}

	CloseBuf( f );

	// Delete empty files if there was an error and we created it
	if	(info->fi_errno && bytes == 0 && !restart)
		DeleteFile( (char *)local_path );
	}
else
	{
	info->fi_errno |= FTPERR_XFER_DSTERR;
	info->fi_ioerr = IoErr();
	}

return bytes;
}