Accessing an FTP site programmatically

Discussions on Software that do not yet fit into any of the current Software fora.

Moderator: Software Moderators

Accessing an FTP site programmatically

Postby FrankParis » Sat 2007 Dec 01 3:25

At work, I have just added an extremely powerful monitoring facility to a program that accounts on our network domain will be using. What I want to do is keep track of who is using the program within the domain and what functions they are using within the program. Each time someone executes the program, a one line file gets written to a public folder on our network documenting what computer did it, the user name and the exact GMT it took place. More refined information is then logged when the users access individual commands within the program. With all this information I can monitor how many people are executing the program and what parts of the program are being used, and what error conditions people are getting themselves into. It's almost like alpha testing through a one way window only the testers don't have to be on the local site but can be anywhere in the world, as long as they're a member of our network domain.

Now I would like to do this outside of our domain: anyone using the program would get their usage logged somewhere on an FTP site. Is this easy to do? I'm using Visual C++ under Windows and MFC. I may be able to figure this out by looking at classes derived from CFile but the question is probably of general interest and language-independent.
User avatar
FrankParis
Full Member
Full Member
 
Posts: 9
Joined: Thu 2007 Nov 15 10:03
Location: Portland, OR

Re: Accessing an FTP site programmatically

Postby Spock » Sat 2007 Dec 01 4:04

  1. I have moved this to, what I hope, is a better location as it seems to pertain more to software development than Internet and networking, and
  2. I personally don't have the expertise to assist you as my last real programming experience ended before 2000 so I'm hoping that, if if the query is positioned better, some of our more experienced members will be able to help.

Good question BTW, thanks for posting.

[Added]
I have just spread you query adrift at the DevelopTheWeb site as well.

You may also wish to visit the Dream.In.Code forum for language specific help.

Whatever you do, if you solve your problem, would you please come back and let us know something about your solution?
User avatar
Spock
Forum Admin
Forum Admin
 
Posts: 2417
Joined: Tue 2005 Jan 18 10:47
Location: MD, USA

Re: Accessing an FTP site programmatically

Postby FrankParis » Sun 2007 Dec 02 1:35

I started programming this experimenting with an FTP site you set me up with. The user name and password are just made up in the example, but they're real in my code and you know what they are. I know you don't know network programming, but you might still have an insight with my current problem. I open an Internet session OK, and then I'm supposed to get an FTP connection with code like this:
Code: Select all
pConnect = internetSession.GetFtpConnection(_T("http://pctalk.info/"),_T("UserName"), _T("secret password"), 21);

As you can see, I'm supposed to give four parameters:
  1. The path to the server
  2. the user name
  3. the password
  4. the port number
When this code executes, I get an FTP error messages that says, "The server name or address could not be resolved." So it doesn't recognize "http://pctalk.info". I tried "ftp.pctalk.info" and that also fails. Any ideas?
User avatar
FrankParis
Full Member
Full Member
 
Posts: 9
Joined: Thu 2007 Nov 15 10:03
Location: Portland, OR

Re: Accessing an FTP site programmatically

Postby Spock » Sun 2007 Dec 02 4:28

For any reading this, yes, it doesn't match the above post exactly. It is in fact a partial reply to a PM where I requested that Frank bring some of his questions out in the open in the forum.

Spock wrote:
fjp wrote:... Is port 21 an FTP standard by any chance, in which case it would also work for the Comcast site?


Might be best to ask Comcast that as I have no-eye-deer. ;)

fjp wrote:... there's no practical limit to the number of files you can have in a UNIX folder, right?


In DOS (and I presume Windows as well) there is a finite limit to the number of file names you may have in the File Allocation Table. It is higher in sub-folders than in the root folder but is still limited. I'm not sure about Linux but I have a feeling it is similar.


Now to answer the actual post above:
FrankParis wrote:... I tried "ftp.pctalk.info" and that also fails. Any ideas?


I would have thought something along the lines of:
Code: Select all
ftp://pctalk.info/<main folder name>/<any sub-folder name(s)>/


or:
Code: Select all
ftp.pctalk.info/<main folder name>/<any sub-folder name(s)>/
User avatar
Spock
Forum Admin
Forum Admin
 
Posts: 2417
Joined: Tue 2005 Jan 18 10:47
Location: MD, USA

Accessing an FTP site programmatically: Done Deal

Postby FrankParis » Sun 2007 Dec 02 7:22

Okay, I've accomplished what I originally set out to do. I'm going to boil my code down as much as possible just to the C++/MFC lines of code that are germain to the problem. The problem is to programmatically put a file from your computer to an FTP site with Visual Studio C++/MFC code, and then read it back to the same place from which it originally came. Just to make this as clean as possible I'm going to have minimal comments. You can look up the various classes and member functions on MSDN.

This is just an example. For the example, we'll use the following:
Server name: "ftp.pctalk.info"
User name: "frankparis"
Password: "@Junk7"
Internet port: 21

I found that the hardest part of this whole exercise was figuring out what the above four parameters should be. Well, the password and Internet port are fairly straightforward. But it took a lot of experimenting to get the Server name and User name right. Maybe if you understand FTP better than I do all that will be obvious to you.

I tried to format the code that follows the same way it looks in Visual Studio but the "code" BBCodes butcher beyond belief what I input so you just have to bear with it. The "code" BBCodes are basically worthless. Rest assured it is well-formatted with proper indentation in the original.

Code: Select all
   CInternetSession internetSession(_T("AnyIdentifier")); // it doesn't matter what "AnyIdentifier" is
   CFtpConnection* pConnect = NULL;
   try
   {
      pConnect = internetSession.GetFtpConnection(_T("ftp.pctalk.info"),  _T("frankparis"), _T("@Junk7"), 21);
   }
   catch (CInternetException* pEx)
                {
                               TCHAR sz[1024];
                               pEx->GetErrorMessage(sz, 1024);
                               CString strTitle(_T("FTP Failure"));
                  CString strTrace;
                  strTrace.Format(_T("%s: %s\n"), strTitle, sz);
                 TRACE(strTrace);
                              pEx->Delete();
               }

              // If the connection is open, do stuff, then close it.
              if (pConnect != NULL)
              {
      TRACE(_T("FTP Success\n"));
      if (pConnect->SetCurrentDirectory(_T("AnyFolderName")))
      {
         TRACE(_T("FTP Success: Set current directory to \"AnyFolderName\"\n"));
         CTime currentTime(CTime::GetCurrentTime());
         CString strGmtTime = currentTime.FormatGmt(_T("%Y.%m.%d %H.%M.%S"));
         CString strLocalLogFilePath;
                                                // AppDataFolder() gets the fully qualified path where you want to store application data; could be anywhere
         strLocalLogFilePath.Format(_T("%s\\%s.txt"), AppDataFolder(), strGmtTime);
         CStdioFile localFile(strLocalLogFilePath, CFile::modeCreate | CFile::modeWrite | CFile::typeText);
         CString strLogLine;
         TCHAR strComputerName[1000], strUserName[1000];
         DWORD lComputer(1000);
         DWORD lName(1000);
         ::GetComputerName(strComputerName, &lComputer);
         ::GetUserName(strUserName, &lName);
         strLogLine.Format(_T("ComputerName=\"%s\"\nUserName=\"%s\"\nLogID=%d\n"), strComputerName, strUserName, 1);
         localFile.WriteString(strLogLine);
         localFile.Close();
         CString strRemoteLogFileName;
         strRemoteLogFileName.Format(_T("%s.txt"), strGmtTime);
                                                // FTP_TRANSFER_TYPE_BINARY so that the newline characters in the formatting aren't lost
                                                // when they're transferred to the FTP site
         if (pConnect->PutFile(strLocalLogFilePath, strRemoteLogFileName, FTP_TRANSFER_TYPE_BINARY))
         {
            CString strLogSuccessMsg;
            strLogSuccessMsg.Format(_T("FTP Success: Put log file, \"%s\"\n"), strRemoteLogFileName);
            TRACE(strLogSuccessMsg);
         }
         else
         {
            TRACE(_T("FTP Failure: Failed to put a log file.\n"));
         }
         ::DeleteFile(strLocalLogFilePath);
                                                // delete the original file so we don't get confused by the results of the next line which gets it back to the same location
         pConnect->GetFile(strRemoteLogFileName, strLocalLogFilePath, FTP_TRANSFER_TYPE_BINARY);
      }
      else
      {
         TRACE(_T("FTP Failure: Failed to set current directory\n"));
      }

      // Close FTP connection
                                pConnect->Close();
                               delete pConnect;
    }
User avatar
FrankParis
Full Member
Full Member
 
Posts: 9
Joined: Thu 2007 Nov 15 10:03
Location: Portland, OR

Re: Accessing an FTP site programmatically

Postby Spock » Mon 2007 Dec 03 1:45

Thanks for the code snippet Frank, it is always nice to have a definite resolution to a problem, even if you had to find it all on your own. Most all my students will find this way over their heads but there are others who visit periodically who may well find this useful.

Thanks again! :applaus1:
User avatar
Spock
Forum Admin
Forum Admin
 
Posts: 2417
Joined: Tue 2005 Jan 18 10:47
Location: MD, USA


Return to General SW

Who is online

Users browsing this forum: No registered users and 2 guests

cron