ftpresp.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 8k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /*****************************************************************************
  2.  *
  3.  *    ftpresp.cpp - Parsing FTP responses
  4.  *
  5.  *****************************************************************************/
  6. #include "priv.h"
  7. /*****************************************************************************
  8.     FUNCTION: FindEndOfStrOrLine
  9.     DESCRIPTION:
  10.         Find the end of the line ('n') or the end of the string ('').
  11. *****************************************************************************/
  12. LPWIRESTR FindEndOfStrOrLine(LPWIRESTR pszString)
  13. {
  14.     while (*pszString != '')
  15.     {
  16.         if (('n' == pszString[0]))
  17.         {
  18.             while (('n' == pszString[0]))
  19.                pszString++;
  20.             break;
  21.         }
  22.         pszString++;
  23.     }
  24.     return pszString;
  25. }
  26. /*****************************************************************************
  27.     FUNCTION: FindFirstMajorResponse
  28.     DESCRIPTION:
  29. *****************************************************************************/
  30. LPWIRESTR FindFirstMajorResponse(LPWIRESTR pszResponse)
  31. {
  32.     while ((pszResponse[0]) && ('-' != pszResponse[3]))
  33.         pszResponse = FindEndOfStrOrLine(pszResponse);
  34.     return pszResponse;
  35. }
  36. /*****************************************************************************
  37.     FUNCTION: GetNextResponseSection
  38.     DESCRIPTION:
  39. *****************************************************************************/
  40. LPWIRESTR GetNextResponseSection(LPWIRESTR pszCompleteResponse, LPWIRESTR * ppszResponseStart)
  41. {
  42.     LPWIRESTR pszNextResponse = NULL;
  43.     // There may be a few minor responses.  Skip over them...
  44.     pszCompleteResponse = FindFirstMajorResponse(pszCompleteResponse);
  45.     // Were we never able to fine a major response?
  46.     if (!pszCompleteResponse[0])
  47.         return NULL;    // No, so return failure.
  48.     // We are off to find the next major response.
  49.     //    We should be looking at a response code.
  50.     ASSERT('-' == pszCompleteResponse[3]);
  51.     // Slop saves us here
  52.     //    Extended response.  Copy until we see the match.
  53.     //  As we copy, we also clean up the lines, removing
  54.     //  the random punctuation servers prepend to continuations.
  55.     //
  56.     //  wu-ftp prepends the extended response code to each line:
  57.     //
  58.     //  230-Welcome to ftp.foo.com.  Please read the rules
  59.     //  230-and regulations in the file RULES.
  60.     //  230 Guest login ok, access restrictions apply.
  61.     //
  62.     //  Microsoft Internet Information Server prepends a space:
  63.     //
  64.     //  230-This is ftp.microsoft.com.  See the index.txt file
  65.     //   in the root directory for more information.
  66.     //  230 Anonymous user logged in as anonymous.
  67.     //
  68.     WIRECHAR szResponseNumber[5];            // example: "230-"
  69.     WIRECHAR szResponseEnd[5];                // example: "230 "
  70.     StrCpyNA(szResponseNumber, pszCompleteResponse, ARRAYSIZE(szResponseNumber));
  71.     ASSERT(4 == lstrlenA(szResponseNumber));
  72.     StrCpyNA(szResponseEnd, szResponseNumber, ARRAYSIZE(szResponseEnd));
  73.     szResponseEnd[3] = ' ';
  74.     pszNextResponse = pszCompleteResponse;
  75.     *ppszResponseStart = pszCompleteResponse;
  76.     do
  77.     {
  78.         //  Skip past the header.
  79.         if (!StrCmpNA(szResponseNumber, pszNextResponse, 4))
  80.             pszNextResponse += 4;    // wu-ftp
  81.         else if ((pszNextResponse[0] == ' ') && (!StrCmpNA(szResponseNumber, &pszNextResponse[1], 4)))
  82.             pszNextResponse += 5;    // ftp.microsoft.com
  83.         else if (pszNextResponse[0] == ' ')
  84.             pszNextResponse++;    // IIS
  85.         //  Skip the rest of the line.
  86.         pszNextResponse = FindEndOfStrOrLine(pszNextResponse);
  87.     }
  88.     while (pszNextResponse[0] && StrCmpNA(pszNextResponse, szResponseEnd, 4));
  89.         /* Now gobble the trailer */
  90.     if ('' == pszNextResponse[0])
  91.         pszNextResponse = NULL;     // We are at the end.
  92.     return pszNextResponse;
  93. }
  94. /*****************************************************************************
  95.     FUNCTION: StripResponseHeaders
  96.     DESCRIPTION:
  97. *****************************************************************************/
  98. void StripResponseHeaders(LPWIRESTR pszResponse)
  99. {
  100.     //    We should be looking at a response code.
  101.     if ((3 < lstrlenA(pszResponse)) && (pszResponse[3] == '-'))
  102.     {
  103.         LPWIRESTR pszIterator = pszResponse;
  104.         WIRECHAR szResponseNumber[5];            // example: "230-"
  105.         WIRECHAR szResponseEnd[5];                // example: "230 "
  106.         BOOL fFirstPass = TRUE;
  107.         StrCpyNA(szResponseNumber, pszResponse, ARRAYSIZE(szResponseNumber));
  108.         ASSERT(4 == lstrlenA(szResponseNumber));
  109.         StrCpyNA(szResponseEnd, szResponseNumber, ARRAYSIZE(szResponseEnd));
  110.         szResponseEnd[3] = ' ';
  111.         do
  112.         {
  113.             //  Skip past the header.
  114.             if (!StrCmpNA(szResponseNumber, pszIterator, 4))
  115.                 RemoveCharsFromStringA(pszIterator, 3);    // wu-ftp
  116.             else if ((pszIterator[0] == ' ') && (!StrCmpNA(szResponseNumber, &pszIterator[1], 4)))
  117.                 RemoveCharsFromStringA(pszIterator, 4);    // ftp.microsoft.com
  118.             else if (pszIterator[0] == ' ')
  119.                 NULL;    // IIS
  120.             if (fFirstPass)
  121.             {
  122.                 fFirstPass = FALSE;
  123.                 RemoveCharsFromStringA(pszIterator, 1);    // IIS
  124.             }
  125.             else
  126.                 pszIterator[0] = ' ';    // Make that new line a space.
  127.             //  Skip the rest of the line.
  128.             pszIterator = FindEndOfStrOrLine(pszIterator);
  129.         }
  130.         while (pszIterator[0] && StrCmpNA(pszIterator, szResponseEnd, 4));
  131.         
  132.         RemoveCharsFromStringA(pszIterator, 4);         // Now gobble the trailer
  133.     }
  134. }
  135. /*****************************************************************************
  136.     FUNCTION: GetMOTDMessage
  137.     DESCRIPTION:
  138. *****************************************************************************/
  139. LPWIRESTR GetMOTDMessage(LPWIRESTR pwResponse, DWORD cchResponse)
  140. {
  141.     LPWIRESTR pszMOTD = NULL;
  142.     LPWIRESTR pszLast = &pwResponse[lstrlenA(pwResponse)];
  143.     LPWIRESTR pszNext = pwResponse;
  144.     LPWIRESTR pszEnd = NULL;
  145.     while (pszNext = GetNextResponseSection(pszNext, &pszLast))
  146.         pszEnd = pszNext;
  147.     if (pszEnd)
  148.         pszEnd[0] = '';   // Terminate it so we don't get the minor responses after our response.
  149.     pszMOTD = (LPWIRESTR) GlobalAlloc(GPTR, (lstrlenA(pszLast) + 1) * sizeof(WIRECHAR));
  150.     if (EVAL(pszMOTD))
  151.     {
  152.         StrCpyA(pszMOTD, pszLast);
  153.         StripResponseHeaders(pszMOTD);
  154.     }
  155.     return pszMOTD;
  156. }
  157. /*****************************************************************************
  158.     FUNCTION: GetFtpResponse
  159.     DESCRIPTION:
  160.         Get the MOTD from the Response
  161. *****************************************************************************/
  162. CFtpGlob * GetFtpResponse(CWireEncoding * pwe)
  163. {
  164.     CFtpGlob * pfg = NULL;
  165.     DWORD cchResponse = 0;
  166.     LPWIRESTR pwWireResponse;
  167.     DWORD dwError;
  168.     InternetGetLastResponseInfoWrap(TRUE, &dwError, NULL, &cchResponse);
  169.     cchResponse++;                /* +1 for the terminating 0 */
  170.     pwWireResponse = (LPWIRESTR)LocalAlloc(LPTR, cchResponse * sizeof(WIRECHAR));
  171.     if (EVAL(pwWireResponse))
  172.     {
  173.         if (SUCCEEDED(InternetGetLastResponseInfoWrap(TRUE, &dwError, pwWireResponse, &cchResponse)))
  174.         {
  175.             LPWIRESTR pwMOTD = GetMOTDMessage(pwWireResponse, cchResponse);
  176.             if (pwMOTD)
  177.             {
  178.                 LPWSTR pwzDisplayMOTD;
  179.                 DWORD cchSize = (lstrlenA(pwMOTD) + 1);
  180.                 pwzDisplayMOTD = (LPWSTR)GlobalAlloc(LPTR, cchSize * sizeof(WCHAR));
  181.                 if (pwzDisplayMOTD)
  182.                 {
  183.                     pwe->WireBytesToUnicode(NULL, pwMOTD, WIREENC_IMPROVE_ACCURACY, pwzDisplayMOTD, cchSize);
  184.                     pfg = CFtpGlob_CreateStr(pwzDisplayMOTD);
  185.                     if (!(EVAL(pfg)))
  186.                         GlobalFree(pwzDisplayMOTD);    // Couldn't track message
  187.                 }
  188.                 GlobalFree(pwMOTD);
  189.             }
  190.         }
  191.         LocalFree(pwWireResponse);
  192.     }
  193.     return pfg;
  194. }