Vas
Vas

Reputation: 85

c++ wininet ftp listing many files bug

I am using wininet to connect to a server. All works fine, upload, download, listing commands etc.... I therefore have a small bug which i don`t know where it comes from. The bug is that some server folders that contains over a 100 files (images for e.x.) are not listed all of them, the listing as far as i tested responds only until 91 files in any folder, over that number it cannot be displayed or seen.

Here is the part of my code that i list the folder with the list -la option to see all files on a server

// Get Current Directory
DWORD FTPdirsize = MAX_PATH + 8;
TCHAR FTPcurDir[MAX_PATH + 8];
if (FtpGetCurrentDirectory(FTPsession, FTPcurDir, &FTPdirsize) == TRUE){
    HINTERNET FTPcommandRecVal;
    BOOL FTPres = FtpCommand(FTPsession, TRUE, FTP_TRANSFER_TYPE_BINARY, FTPsearchParam, NULL, &FTPcommandRecVal);
    if (FTPres && FTPcommandRecVal){
        DWORD dwRead;
        char szBuf[8192];
        string FullStrBuf;
        while (InternetReadFile(FTPcommandRecVal, szBuf, 8192, &dwRead) && dwRead != 0){
            FullStrBuf = szBuf;
            FullStrBuf = FullStrBuf.substr(0, dwRead);
        }
        InternetCloseHandle(FTPcommandRecVal);
        int nIdx = 0;
        char szLine[8192] = { 0 };
        char c;
        int TheEndLenght = FullStrBuf.length();
        for (int i = 0; i < TheEndLenght - 1; i++){
            c = FullStrBuf[i];
            if (c == '\r' || c == '\n' || c == '\0'){
                if (nIdx){
                    struct ftpparse fp;
                    int nRes = ftpparse(&fp, szLine, nIdx);
                    if (nRes){
                        // Name
                        wstring FTPsrvFFnameW = fp.strName;
                        FTPList.push_back(FTPsrvFFnameW);
                    }
                }
                for (int j = 0; j < sizeof(szLine); j++){
                    szLine[j] = 0;
                }
                nIdx = 0;
            }
            else{
                szLine[nIdx++] = c;
            }
        }

        ////... print function for FTPList
    }
    else{
        InternetCloseHandle(FTPcommandRecVal);
        /////... ERROR HANDLING
    }
}
else{
    /////... ERROR HANDLING
}

Note that i was using a 4096 buffer instead of 8192 and it was listing only until 37 files among all files on a folder. I change it to 8192 and it lists until 91 files, any other value above 8192 statys the same to my tests so i guess there must be something else also that doesn`t allow all files to be listed properly and has a limitation. The server also has no limitation in file listing through ftp clients.

I also use this ftpparse from this link https://cr.yp.to/ftpparse.html

Any help is much appreciated to solve this bug.

Upvotes: 1

Views: 177

Answers (1)

Barmak Shemirani
Barmak Shemirani

Reputation: 31599

The old information in FullStrBuf is lost after calling FullStrBuf = szBuf; Use instead:

while (InternetReadFile(FTPcommandRecVal, szBuf, 8192, &dwRead) && dwRead != 0)
{
    FullStrBuf.append(szBuf, dwRead);
}

Suggestion:

If FullStrBuf doesn't contain '\0' in the middle, you can use std::find or std::find_first_of to break the string. For example, assuming that FullStrBuf contains either "\n" or "\r\n" for new line:

for(size_t start = 0, pos = 0; pos != string::npos;)
{
    pos = FullStrBuf.find_first_of("\r\n", start);
    string s = FullStrBuf.substr(start, pos - start);
    if(s.size())
    {
        cout << s << endl;
        //ftpparse ...
    }
    start = pos + 1;
}

Upvotes: 1

Related Questions