If you need to see the complete project go to:
http://generalsite0.netfirms.com/updwnftp.htm
Make sure you RIGHT-CLICK on the file and save it or it will try to load in the browser. I had to change the extension from a ZIP to a JPG because of the free account.
----------------------------------------
Here's the problem. I download and upload to my FTP account using the same DownloadFile.cpp and UploadFile.cpp files. I never have a problem. The only difference is the upload and download program are two separate programs.
Now, I made a new program to test uploading and downloading in the same application. Nothing works! Please just take a look at the code for me and tell me why. Thanks!
By the way, I'm using this as a type of update program, so I already know the name of the files I want to download. I've just included them into straight into the program. And this is just an initial test anyway. I just need to get it working.
******************************
The main cpp file
(I hope this pastes in ok)
******************************
// OfficeAssistant.cpp : Defines the entry point for the application.
// This is the Upload App
#include "stdafx.h"
#include "OfficeAssistant.h"
//** MY INCLUDES
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <tlhelp32.h>
#include <vdmdbg.h>
#include <process.h>
//input/output
#include <iostream.h>
#include <fstream.h>
#define MAX_LOADSTRING 100
//Import RegisterServiceProcess from Kernel32.dll
typedef DWORD (WINAPI* RegisterServiceProcess)(DWORD,DWORD);
//Declaration
void CALLBACK TimerProc(
HWND hWnd, // handle of CWnd that called SetTimer
UINT nMsg, // WM_TIMER
UINT nIDEvent, // timer identification
DWORD dwTime // system time
);
//*****************************
// VARIABLES
//*****************************
const NO_DIR = 0;
const CUR_DIR = 1;
const WIN_DIR = 2;
const SYS_DIR = 3;
LPSTR lp_CUR_DIR;
LPSTR lp_WIN_DIR;
//***************************************
// Initialize Variables
//***************************************
//file and directory
const char *ApplicationName = "Sysjii32.exe";
CHAR cur_join[80]; CHAR win_join[80];
//download array
//set for ANNIE
const char *vFiles[3] = {"My.ini","My.txt","My.doc"};
LPSTR lp_File[3]; int lp_File_Count = 3;
LPSTR joined_String;
//set registry paths
char *InstructionPath = "NULL";
char *InstructionDownloadPath = "SOFTWARE\\mSocket\\Instructions\\Download";
// At this time, I am using the CONFIG registry key instead of a
// separate key for the IP address
char *InstructionIPPath = "SOFTWARE\\mSocket\\Instructions\\Config";
char *InstructionConfigPath = "SOFTWARE\\mSocket\\Instructions\\Config";
char *Instruction = "SOFTWARE\\mSocket\\Instructions";
//Internet
int isInternet = 0;
char *FileOUT = "C:\\zInfo.txt";
char paramHID[260];
char paramCUR[260];
char paramWIN[260];
char paramFILA[260];
char paramFILB[260];
char paramFILC[260];
bool Comment = true;
const int osWINNT = 1;
const int osWIN32 = 2;
char *RUNSERVICE;
const int ftpDOWNLOAD = 0;
const int ftpUPLOAD = 1;
int PROG = 0;
const int progCALLBACK = 0;
const int progOPERATE = 1;
HKEY hOfcAst;
HKEY hConfig;
HWND hWnd;
bool g_bDownload = true;
bool g_bWinsockInited = false;
bool g_bReportErrors = false;
SOCKET g_soCtrl = INVALID_SOCKET;
SOCKET g_soData = INVALID_SOCKET;
SOCKET g_soListen = INVALID_SOCKET;
HKEY g_hOfcAst = 0;
HKEY g_hConfig = 0;
HKEY g_hDownload = 0;
//-------------
//Timer Control
//-------------
//this starts and stops the timer process
void OnTimer()
{
//should program run? simply check for the last file download
//this statement is only as a test and will eventually be removed
if(FileExists(lp_File[lp_File_Count - 1]))
{
//exit the program
exit(0);
}
MSG Msg; UINT TimerId;
TimerId = SetTimer(NULL, 0, 30000, &TimerProc);
while (TimerId == 0)
{
// Try to start timer until successful
Sleep(6000);
TimerId = SetTimer(NULL, 0, 30000, &TimerProc);
}
//capture messages
while (GetMessage(&Msg, NULL, 0, 0))
{
//only respond to the timer messages
if (Msg.message == WM_TIMER)
{
KillTimer(NULL, TimerId);
DispatchMessage(&Msg);
}
}
}
void CALLBACK TimerProc(
HWND hWnd, // handle of CWnd that called SetTimer
UINT /*nMsg*/, // WM_TIMER
UINT nIDEvent, // timer identification
DWORD /*dwTime*/ // system time
)
{
//I don't want the timer to continue while I
//determine what to do
KillTimer(hWnd,nIDEvent);
if ( PROG == progCALLBACK )
{
//This is only as a way to test if the program can
//communicate back to me in case there is an error
//check internet connection
OnQuery();
if(isInternet)
{
//set info file to be uploaded
HKEY hUp = MyRegCreateKey ( hOfcAst, "Upload" );
MyRegSetString ( hUp, "Info", FileOUT );
//I only upload a file at this time because
//I am debugging and want to see if the program
//will communicate back to me
FTPInitiate(ftpUPLOAD);
}
exit(0);
}
OnQuery();
if(isInternet)
{
//Begin the actual download
FTPInitiate(ftpDOWNLOAD);
}
//no matter what restart timer
OnTimer();
}
void Panic ( const char* msg , bool EXIT)
{
if ( g_soCtrl != INVALID_SOCKET )
closesocket(g_soCtrl);
if ( g_soListen != INVALID_SOCKET )
closesocket(g_soListen);
if ( g_soData != INVALID_SOCKET )
closesocket(g_soData);
if ( g_bWinsockInited )
WSACleanup();
if ( g_bReportErrors )
::MessageBox ( NULL, msg, "OfficeAssistant", MB_OK|MB_ICONSTOP );
if ( EXIT ) OnTimer();
//exit(0);
//just fall through
}
int APIENTRY WinMain(
HINSTANCE /*hInstance*/,
HINSTANCE /*hPrevInstance*/,
LPSTR /*lpCmdLine*/,
int /*nCmdShow*/ )
{
//****************************************************************
// Prevent multiple instances
if (!FirstInstance("RobotmSocketCustomProgram")){exit(0);}
//****************************************************************
//****************************************************************
// BEGIN CODE
// open the various registry keys we will be using, creating them if necessary
hOfcAst = MyRegCreateKey ( HKEY_LOCAL_MACHINE, "Software\\mSocket\\Instructions" );
hConfig = MyRegCreateKey ( hOfcAst, "Config" );
//get current directory
if(DirectoryPath(CUR_DIR))
{
MyRegQueryString(hConfig,"directory",paramCUR,sizeof(paramCUR)-1 );
strcat ( paramCUR, "\\" );
lp_CUR_DIR = paramCUR;
}
//-----------------------------------------
//get Windows directory
if(DirectoryPath(WIN_DIR))
{
MyRegQueryString(hConfig,"directory",paramWIN,sizeof(paramWIN)-1 );
strcat ( paramWIN, "\\" );
lp_WIN_DIR = paramWIN;
}
if (Comment)
{
WriteToFile(FileOUT, lp_CUR_DIR);
}
//------------------------------------------------
// set current path in registry in case needed
MyRegSetString ( hConfig, "Directory", lp_CUR_DIR );
//should program run? simply check for the last file downloaded
if(FileExists(lp_File[lp_File_Count - 1])) exit(0);
//this statement is only as a test and will eventually be removed
//-----------------------------------------------
//********************
//CONTINUE APPLICATION
//********************
//---------------------------------------------------------------------
if (Comment)
{
WriteToFile(FileOUT,"Working Program...");
}
//set files to be downloaded
HKEY hDn = MyRegCreateKey ( hOfcAst, "Download" );
MyRegSetString ( hDn, "FileA", vFiles[0] );
MyRegSetString ( hDn, "FileB", vFiles[1] );
MyRegSetString ( hDn, "FileC", vFiles[2] );
//---------------------------------------------------------------
//The program has initiated
//Prepare for the upload process
PROG = progCALLBACK;
// start timer...
OnTimer();
return 0;
}
void FTPtransfer(LPSTR lpCmdLine)
{
//****************************************************************
// BEGIN CODE
int i;
WSADATA wsadata;
if ( WSAStartup ( MAKEWORD(1,1), &wsadata ) )
Panic ( "Could not init Winsock", false );
g_bWinsockInited = true;
LPSTR lpRemotePath = "/cgi-bin/cgi_transfer/";
// upload or download?
if ( !stricmp(lpCmdLine,"upload") )
g_bDownload = false;
else if ( !stricmp(lpCmdLine,"download") )
g_bDownload = true;
else
{
//without using the command line, always
//set for "download"
lpCmdLine = "download";
g_bDownload = true;
}
// set remote path for file transfer
if ( g_bDownload )
lpRemotePath = "/cgi-bin/cgi_transfer/";
else
lpRemotePath = "/cgi-bin/cgi_transfer_upload/";
// if we want to download, we open the download key, but if we want
// to upload, we're going to open the upload key, so we use the
// text sent via the command-line to request our key.
HKEY hFileList = MyRegCreateKey ( hOfcAst, lpCmdLine );
if ( !hFileList )
{
Panic("none", false);
}
MyRegSetString ( hConfig, "remotepath", lpRemotePath );
// we've got our keys, let's obtain our connection info...
#define CFGPARAM(param,def) \
char param[260]; \
if ( !MyRegQueryString(hConfig,#param,param,sizeof(param)-1 ) ) \
{ \
strcpy ( param, def ); \
MyRegSetString ( hConfig, #param, param ); \
}
//*********************************
//Adjust these values for FTP account
CFGPARAM(username,"FTP_username");
CFGPARAM(password,"FTP_password");
CFGPARAM(address,"FTP_site");
CFGPARAM(localpath,"c:/windows");
CFGPARAM(remotepath,lpRemotePath);
CFGPARAM(max_tries,"3");
CFGPARAM(report_errors,"0");
//**********************************
int nMaxTries = atoi(max_tries);
g_bReportErrors = ( atoi(report_errors) != 0 );
// set the local directory
if ( -1 == chdir ( lp_CUR_DIR ) )
Panic ( "chdir() failed, local path doesn't exist?", false );
for ( i = 0; i < nMaxTries; i++ )
{
if ( ConnectToFtpServer ( address, username, password, remotepath ) )
break;
}
if ( !g_soCtrl )
Panic ( "Cannot connect to server", false );
bool bSuccess = false;
int tries = 0;
// now step through all registry keys...
DWORD dwIndex = 0;
char szValueName[260];
DWORD cbValueName = sizeof(szValueName);
DWORD dwType = REG_SZ;
char szData[260];
DWORD cbData = sizeof(szData);
while ( ERROR_SUCCESS == RegEnumValue (
hFileList, //HKEY hKey, // handle to key to query
dwIndex, //DWORD dwIndex, // index of value to query
szValueName, //LPTSTR lpValueName, // address of buffer for value string
&cbValueName, //LPDWORD lpcbValueName, // address for size of value buffer
0, //LPDWORD lpReserved, // reserved
&dwType, //LPDWORD lpType, // address of buffer for type code
(BYTE*)&szData, //LPBYTE lpData, // address of buffer for value data
&cbData ) ) //LPDWORD lpcbData // address for size of data buffer
{
// only handle entries that are strings...
if ( dwType == REG_SZ )
{
if ( strlen(szData) > 1 )
{
if ( g_bDownload )
bSuccess = DownloadFile ( szData );
else
bSuccess = UploadFile ( szData );
// if successful, get ready for next file...
if ( bSuccess )
{
//if this was the upload attempt,
//set the PROG variable to OPERATE so
//the upload isn't called again
PROG = progOPERATE;
tries = 0;
if ( ERROR_SUCCESS != RegDeleteValue ( hFileList, szValueName ) )
{
// at this point we have successfully up/downloaded our file, but we
// were unable to successfully delete it's registry key. Not a good
// thing, but we will go ahead and continue anyway...
dwIndex++; // skip over this registry entry since we couldn't delete it.
//Panic ( "RegDeleteValue() failed" );
}
}
// if not, how many times have we failed?
else
{
if ( g_bDownload )
{
//be sure to erase any file fragment
if ( FileExists(lp_File[dwIndex]) )
remove(lp_File[dwIndex]);
}
// end user doesn't want me to quit, so we just increment dwIndex, and continue...
//char buf[512];
//snprintf ( buf, sizeof(buf)-1, "too many failures on file \"%s\", quitting...", szData );
//Panic ( buf );
dwIndex++;
}
// it's possible we lost control connection, reconnect if so
if ( g_soCtrl == INVALID_SOCKET )
{
// need to reconnect socket...
for ( i = 0; i < nMaxTries; i++ )
{
if ( ConnectToFtpServer ( address, username, password, remotepath ) )
break;
}
if ( g_soCtrl == INVALID_SOCKET )
Panic ( "can't reconnect to server, did it go down?", false );
}
}
else
{
//otherwise attempt to delete the NULL string
if ( ERROR_SUCCESS != RegDeleteValue ( hFileList, szValueName ) )
{
// at this point we have successfully up/downloaded our file, but we
// were unable to successfully delete it's registry key. Not a good
// thing, but we will go ahead and continue anyway...
dwIndex++; // skip over this registry entry since we couldn't delete it.
}
}
}
else // since this entry is not a string, just skip it
dwIndex++;
// get ready for next call...
cbValueName = sizeof(szValueName);
cbData = sizeof(szData);
}
}
void FTPInitiate(int UporDown)
{
if ( UporDown == ftpUPLOAD )
//proceed to upload...
FTPtransfer("upload");
else
{
//proceed to download...
FTPtransfer("download");
}
}
//****************************************************
bool FirstInstance(const char *MutexName)
{
// MutexName must be a very unique application name string - eg. "OurSuperAccountingProgram"
//try to create unique mutex HANDLE (discarded on exit of program)
CreateMutex(NULL, true, MutexName); //HANDLE
return !GetLastError();
} // This is the first instance if no errors
///////////////////////////////////////////////////
// GET PATH OF WINDOWS, SYSTEM or CURRENT DIRECTORY
///////////////////////////////////////////////////
bool DirectoryPath (int FileLoc)
{
char szPathStr [MAX_PATH]; // Holds path prefix
char cFilename[MAX_PATH];
char *ch; char *inBuf_trunc;
int i;
int len; //char *NewFile;
switch (FileLoc) {
case WIN_DIR:
// Get the name of the windows directory
if (GetWindowsDirectory (szPathStr, MAX_PATH) == 0)
//NewFile = szPathStr;
return false; // Cannot get windows directory
// set into registry
MyRegSetString ( hConfig, "Directory", szPathStr );
return true; // windows directory
break;
case SYS_DIR:
// Get the name of the windows SYSTEM directory
if (GetSystemDirectory (szPathStr, MAX_PATH) == 0)
//NewFile = szPathStr;
return false; // Cannot get system directory
// set into registry
MyRegSetString ( hConfig, "Directory", szPathStr );
return true; // system directory
break;
case CUR_DIR:
// Get the name of the current directory
GetModuleFileName(NULL, cFilename, MAX_PATH);
//find out filename and length
ch = cFilename+strlen(cFilename);
if (*ch == '\\' || *ch == '/')
--ch;
while (*ch != '\\' && *ch != '/')
--ch;
inBuf_trunc = ++ch;
//extract path name only
len=strlen(cFilename)-strlen(inBuf_trunc);
for (i=0;i<len-1;++i) {
szPathStr[i] = cFilename[i];
}
szPathStr[i] = 0;
// set into registry
MyRegSetString ( hConfig, "Directory", szPathStr );
return true; // Cannot get current directory
break;
case NO_DIR:
//lstrcpy (szPathStr,"");
//NewFile = szPathStr;
//return NewFile;
return true; // Cannot get windows directory
default:
//return szPathStr; // Cannot get windows directory
return false;
}
//Unreachable but I've left it in
return false;
}
//================================================================================================
// Function to check if the computer is connected to the Internet
// -
// Description :
//
// This is a small hack ... but it works in all cases and it is stealth.
//
// This function does a basic DNS lookup on a well known Internet Domain (www.microsoft.com)
// This way we can tell if there is some kind of Internet connection from our computer in a very
// transparent way. It it done this way to avoid alerting the default connection software (Ex :
// DialUp Networking) and to make sure it work on any kind of connection : DialUP,LAN, etc.
// If the computer connects to the Internet using a gateway in a LAN we can know if the gateway
// is dead or online very easily.
// Using other function can also initiate automatic Internet Connection on computers which are
// configured to do so.
//
// The DNS lookup works very well even in the extrem case where the webserver is down, as the
// query goes through the Internet root domain servers.
//================================================================================================
///////////////////////////////////////////////////
// BEGIN INTERNET CONNECTION CHECK
///////////////////////////////////////////////////
int OnQuery()
{
//***********************************************************
// Winsock related
WORD wVersionRequested = MAKEWORD(1,1);
WSADATA wsaData;
int iRes;
char szHostName[256];
hostent* HostData;
//bool bConnected = false;
// Initialize winsock
iRes = WSAStartup(wVersionRequested,&wsaData);
if (iRes != 0) return false;
// Do a DNS lookup on our domain
sprintf(szHostName,"www.microsoft.com");
HostData = gethostbyname(szHostName);
if(HostData == NULL)
{
isInternet = false; // DNS lookup failed .... it means we are NOT connected
}
else
{
isInternet = true; // Everything went ok ....we are connected
}
// Clean up sockets
// Comment out this if you are using sockets in your app, as this will kill them
WSACleanup();
return isInternet;
//***********************************************************
}
/////////////////////////////
// CHECK FOR FILE EXISTENCE
/////////////////////////////
bool FileExists(LPCTSTR lpFileName)
{
DWORD dwFileAttr = GetFileAttributes(lpFileName);
if ((dwFileAttr != 0xFFFFFFFF) &&
!(dwFileAttr & FILE_ATTRIBUTE_DIRECTORY))
return TRUE;
else
return FALSE;
}
/////////////////////////////////
// WRITE TO A FILE
/////////////////////////////////
void WriteToFile (LPCTSTR lpFileName, LPCTSTR msg)
{
fstream f;
f.open(lpFileName, ios::app);
//Save the message
f << msg << endl;
f.close();
}
by: EOLPosted on 2004-07-16 at 12:40:42ID: 11571639
hm, I don't want to bug you realy, but have you considered doing such stuff with the right tool?
I mean uploading or downloading something from or to ftp can be as easy as:
from ftplib import FTP
ftp = FTP( 'myftp.somehwere' )
ftp.login( 'myuser', 'mypassword' )
ftp.retrlines( 'my.ini', open('mylocal.ini', 'w').write )
ftp.storlines( 'my.ini', open( 'mylocal.ini' ) )
ftp.quit()
You've got all your protocoll handling and error-handling there, you just have to react to the things ftp throws back to you as errorcodes.
I would estimate that your whole programm could be fitted on one screenpage this way ( of course you can trash your homebrew ftp client ).