d'aprés ce que j'ai compris le flag "INTERNET_FLAG_ASYNC" n'est pas supporté c pourquoi cela provoque un assert failed... maintenant je vois pas trop comment je vais faire dans mon implémentatoin pour rendre les transfert asynchrones...
voilà le code:
"
#include "CFtp.h"
// constructeur
CFtp::CFtp() : //CInternetSession("NTV Factory ActiveX FTP Client", 1, INTERNET_OPEN_TYPE_PRECONFIG,
// NULL, NULL, INTERNET_FLAG_ASYNC), m_pFtpConnection(NULL)
CInternetSession("NTV Factory ActiveX FTP Client" ), m_pFtpConnection(NULL)
{
strcpy(Error, "no error" );
NumError = 0;
ErrorLength = 9;
strcpy(BaseDirectory, "\\" );
Status = NOT_CONNECTED;
// c à l'utilisateur de l'appeler explicitement
//EnableStatusCallback(TRUE);
}
// destructeur
CFtp::~CFtp() {
CloseConnect();
Close();
}
// fin de connection (détruit m_pFtpConnection)
void CFtp::CloseConnect()
{
if(m_pFtpConnection) {
m_pFtpConnection->Close();
delete m_pFtpConnection;
m_pFtpConnection = NULL;
}
Status = NOT_CONNECTED;
}
// connection au serveur ftp (crée m_pFtpConnection)
// retourne 0 si succès, sinon Error contient le message d'erreur
HRESULT CFtp::Connect(const char* ServerName, const char* Login, const char* Password,
INTERNET_PORT Port, BOOL Passive) {
if(m_pFtpConnection) {
strcpy(Error, "Already connected" );
return E_FAIL;
}
// la solution pour de l'async, serait de créer un thread qui crée la connection FTP
// cale ne va-t-il pas poser problème dans une classe ??
//CreateThread(NULL, 0, ThreadProc, this, 0 , &ThreadID);
JI_ERROR(m_pFtpConnection = GetFtpConnection(ServerName, Login, Password, Port, Passive));
DWORD size = MAX_PATH;
JI_ERROR(m_pFtpConnection->GetCurrentDirectory(BaseDirectory, &size));
return 0;
}
// envoie d'un fichier sur le serveur,
// retourne 0 si succès, sinon Error contient le message d'erreur
HRESULT CFtp::PutFile(const char* LocalFile, const char* RemoteFile) {
CHECK_CONNECT;
if((!LocalFile)||(!RemoteFile)||(!strcmp(LocalFile, "" ))||(!strcmp(RemoteFile, "" ))) {
strcpy(Error, "PutFile: Invalid arguments" );
return E_INVALIDARG;
}
// il faut décomposer le nom de fichier en chemin + nom de fichier effectif
const char* p = RemoteFile;
// on se place au dernier '/'
while(*p) p++; do p--; while((*p != '/'&&(p > RemoteFile));
int nbchar = p - RemoteFile;
// on sauvegarde le repertoire d'appel
CString CurrentDir;
JI_ERROR(m_pFtpConnection->GetCurrentDirectory(CurrentDir));
// s'il y il y a un repertoire on le stocke dans une variable à part
if( (nbchar)||(*p == '/' ) {
char* Directory = (char*)malloc((nbchar+2)*sizeof(char));
if(!Directory) {
strcpy(Error, "PutFile: Out of memory !" );
return E_OUTOFMEMORY;
}
strncpy(Directory, RemoteFile, nbchar+1);
// on termine la chaine de car
*(Directory+nbchar+1) = '\0';
if(SetRemoteDirectory(Directory, TRUE)) {
free(Directory);
return E_FAIL;
}
free(Directory);
// RemoteFile ne contient que le nom de fichier
RemoteFile += nbchar+1;
}
JI_ERROR(m_pFtpConnection->PutFile(LocalFile, RemoteFile));
// ptêt devoir utiliser ::CreateFile
// m_pFtpConnection->OpenFile
// et ::ReadFile / CInternetFile::Write en boucle ....
// (dans le callback pour ne pas bloquer l'exécution ?? )
// on restore le repertoire d'appel
JI_ERROR(m_pFtpConnection->SetCurrentDirectory(CurrentDir.GetBuffer(1)));
return 0;
}
// envoie un repertoire et son contenu sur le serveur
// retourne 0 si succès, sinon Error contient le message d'erreur
// ne modifie pas le repertoire courant
HRESULT CFtp::PutDirectory(const char* LocalDirectory, const char* RemoteDirectory) {
CHECK_CONNECT;
if((!LocalDirectory)||(!RemoteDirectory)) {
strcpy(Error, "PutDirectory: Invalid arguments" );
return E_INVALIDARG;
}
// on sauvegarde le repertoire d'appel
CString CurrentDir;
JI_ERROR(m_pFtpConnection->GetCurrentDirectory(CurrentDir));
// on copie le repertoire source sur le serveur
HRESULT rval = RecPutDirectory(LocalDirectory, RemoteDirectory) ;
// on restore le repertoire courant
JI_ERROR(m_pFtpConnection->SetCurrentDirectory(CurrentDir.GetBuffer(1)));
return rval;
}
const char* CFtp::GetError()
{
return Error;
}
// Va dans le répertoire spécifié sur le serveur
// (créer le répertoire si besoin si Create = TRUE)
// retourne 0 si succès, sinon Error contient le message d'erreur
// appelle RecRemoteDirectory();
HRESULT CFtp::SetRemoteDirectory(const char* RemoteDirectory, BOOL Create) {
CHECK_CONNECT;
if(!RemoteDirectory) {
strcpy(Error, "SetRemoteDirectory: Invalid arguments" );
return E_INVALIDARG;
}
// si le repertoire commence par un slash alors on se place dans le repertoire de base du serveur ftp
if(*RemoteDirectory == '/' {
JI_ERROR(m_pFtpConnection->SetCurrentDirectory(BaseDirectory));
// ensuite on peut virer le(s) premier(s) slash(s)
while(*RemoteDirectory == '/' RemoteDirectory++;
}
return RecRemoteDirectory(RemoteDirectory, Create);
}
// retourne le repertoire courant dans 'RemoteDirectory'
// retourne 0 si succès, sinon Error contient le message d'erreur
HRESULT CFtp::GetRemoteDirectory(CString& RemoteDirectory) {
CHECK_CONNECT;
JI_ERROR(m_pFtpConnection->GetCurrentDirectory(RemoteDirectory));
int i = 0;
CString sav = RemoteDirectory;
// on compte le nb de car dans le rep. de base
while( *(BaseDirectory + i) != '\0' i++;
// on retire le rep. de base dans le rep. courant
char* p = sav.GetBuffer(1);
char* j = RemoteDirectory.GetBuffer(1);
strcpy(j, p + i);
// et on ajoute un slash '/' final
strcat(j ,"/" );
RemoteDirectory.ReleaseBuffer();
return 0;
}
// ********************* protected ******************** //
// Va dans le répertoire spécifié sur la machine locale
// retourne 0 si succès, sinon Error contient le message d'erreur
HRESULT CFtp::SetLocalDirectory(const char* LocalDirectory) {
CHECK_CONNECT;
if(!LocalDirectory) {
strcpy(Error, "SetLocalDirectory: Invalid arguments" );
return E_INVALIDARG;
}
if(!SetCurrentDirectory(LocalDirectory)) {
Msg(Error, "SetLocalDirectory: Cannot set current directory %s", LocalDirectory);
return E_FAIL;
}
return 0;
}
// ********************* private ********************* //
HRESULT CFtp::RecRemoteDirectory(const char* RemoteDirectory, BOOL Create = TRUE) {
// on enlève le slash '/' de début si besoin
while(*RemoteDirectory == '/' RemoteDirectory++;
// on a fini: on est dans le bon répertoire
if(*RemoteDirectory == '\0' return 0;
if( (!strcmp((char*)RemoteDirectory, "." ))||(!strcmp((char*)RemoteDirectory, "./" )) ) return 0;
// on se place au premier '/' s'il existe
const char* p = RemoteDirectory;
while((*p)&&(*p != '/') p++; // un foirage ici ????
int nbchar = p - RemoteDirectory;
char* ImDir = (char*)malloc((nbchar+2)*sizeof(char));
if(!ImDir) {
strcpy(Error, "RecRemoteDirectory: Out of memory !" );
return E_OUTOFMEMORY;
}
strncpy(ImDir, RemoteDirectory, nbchar);
*(ImDir+nbchar) = '\0';
// on essaie de le créer
if(Create) m_pFtpConnection->CreateDirectory(ImDir);
// et on y va
HRESULT rval;
LI_ERROR(m_pFtpConnection->SetCurrentDirectory(ImDir));
free(ImDir);
if(!rval) return E_FAIL; // le LI_ERROR le place à 0 si echec
RemoteDirectory = p;
return RecRemoteDirectory(RemoteDirectory, Create);
}
// fonction récursive appelé par PutDirectory()
HRESULT CFtp::RecPutDirectory(const char* LocalDirectory, const char* RemoteDirectory) {
CHECK_CONNECT;
if((!LocalDirectory)||(!RemoteDirectory)) {
strcpy(Error, "PutDirectory: Invalid arguments" );
return E_INVALIDARG;
}
// on se place dans le repertoire cible local
if(SetLocalDirectory(LocalDirectory)) return E_FAIL;
// on fait de même dans le rep distant
if(SetRemoteDirectory(RemoteDirectory, TRUE)) return E_FAIL;
// pour chaque fichier: on le stocke sur le serveur
// pour chaque repertoire on appelle la fonction récursivement
WIN32_FIND_DATA find_data;
HANDLE File = FindFirstFile("*.*", &find_data);
if(File == INVALID_HANDLE_VALUE) {
Msg(Error, "Cannot find file in %s", LocalDirectory);
return E_FAIL;
}
while(File) {
char* FileName = find_data.cFileName;
if(find_data.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) {
if( (strcmp(FileName, "." ))&&(strcmp(FileName, "./" ))&&
(strcmp(FileName, ".." ))&&(strcmp(FileName, "../" )) ) {
if(RecPutDirectory(FileName, FileName)) return E_FAIL;
}
}
else {
if(PutFile(FileName, FileName)) return E_FAIL;
}
if(!FindNextFile(File, &find_data)) {
FindClose(File);
File = 0;
}
}
// on remonte l'arborescence d'un niveau pour revenir au répertoire courant
// lors de l'appel de la fonction
if(SetLocalDirectory(".." )) return E_FAIL;
if(SetRemoteDirectory("..", FALSE)) return E_FAIL;
return 0;
}
// ******************* callback ************************ //
// on surchage l'évenement OnStatusCallback pour afficher une progression du telechargement
void CFtp::OnStatusCallback(DWORD dwContext, DWORD dwInternetStatus,
LPVOID lpvStatusInformation, DWORD dwStatusInformationLength) {
AFX_MANAGE_STATE( AfxGetAppModuleState( ) );
if(dwContext == 1) {
switch(dwInternetStatus) {
case INTERNET_STATUS_CONNECTING_TO_SERVER: Status = CONNECTING; break;
case INTERNET_STATUS_CONNECTED_TO_SERVER: Status = CONNECTED; break;
case INTERNET_STATUS_SENDING_REQUEST: Status = SENDING; break;
case INTERNET_STATUS_REQUEST_SENT: Status = SENT; break;
case INTERNET_STATUS_RECEIVING_RESPONSE: Status = RECEIVING; break;
case INTERNET_STATUS_RESPONSE_RECEIVED: Status = RECEIVED; break;
case INTERNET_STATUS_CLOSING_CONNECTION: Status = CLOSING; break;
case INTERNET_STATUS_CONNECTION_CLOSED: Status = CLOSED; break;
case INTERNET_STATUS_REQUEST_COMPLETE:
{
Status = COMPLETE;
INTERNET_ASYNC_RESULT* result = (INTERNET_ASYNC_RESULT*) lpvStatusInformation;
if( (dwStatusInformationLength == ERROR_INTERNET_EXTENDED_ERROR) ||
(result->dwError != ERROR_SUCCESS) ) { // on affiche l'erreur
ErrorLength = ErrorMaxLength;
InternetGetLastResponseInfo(&NumError, Error, &ErrorLength);
msg(Error);
}
else { // pas d'erreur
msg("reçu un INTERNET_STATUS_REQUEST_COMPLETE sans erreur !" );
}
}
break;
default:
msg("reçu un statuscallback !" );
}
}
}
"
[jfdsdjhfuetppo]--Message édité par ZZZzzz le 30-04-2002 à 14:31:04--[/jfdsdjhfuetppo]