inet.cpp 71 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #include <afxtempl.h>
  12. #include <afxinet.h>
  13. #pragma warning(disable: 4706) // assignment within conditional
  14. #ifdef AFX_INET_SEG
  15. #pragma code_seg(AFX_INET_SEG)
  16. #endif
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21. #define new DEBUG_NEW
  22. #ifdef _AFXDLL
  23. #pragma comment(lib, "wininet.lib")
  24. #endif
  25. /////////////////////////////////////////////////////////////////////////////
  26. // non-localized useful strings
  27. typedef struct tagServiceTable {
  28. DWORD dwService;
  29. LPCTSTR pstrIdentifier;
  30. } SvcTable;
  31. AFX_STATIC_DATA const TCHAR _afxURLftp[] = _T("ftp://");
  32. AFX_STATIC_DATA const TCHAR _afxURLgopher[] = _T("gopher://");
  33. AFX_STATIC_DATA const TCHAR _afxURLhttp[] = _T("http://");
  34. const LPCTSTR CHttpConnection::szHtmlVerbs[] = {
  35. _T("POST"),
  36. _T("GET"),
  37. _T("HEAD"),
  38. _T("PUT"),
  39. _T("LINK"),
  40. _T("DELETE"),
  41. _T("UNLINK"),
  42. };
  43. /////////////////////////////////////////////////////////////////////////////
  44. // map of HINTERNETs to CInternetSessions* for callbacks
  45. // forward declared because we need a #pragma -- see end of this file
  46. class CSessionMapPtrToPtr : public CMapPtrToPtr
  47. {
  48. private:
  49. CCriticalSection m_sect;
  50. public:
  51. CSessionMapPtrToPtr() { }
  52. ~CSessionMapPtrToPtr() { }
  53. void SetAt(HINTERNET hInternet, CInternetSession* pSess)
  54. {
  55. m_sect.Lock();
  56. CMapPtrToPtr::SetAt(hInternet, pSess);
  57. m_sect.Unlock();
  58. }
  59. void RemoveKey(HINTERNET hInternet)
  60. {
  61. m_sect.Lock();
  62. CMapPtrToPtr::RemoveKey(hInternet);
  63. m_sect.Unlock();
  64. }
  65. BOOL Lookup(HINTERNET hInternet, CInternetSession*& refpSession)
  66. {
  67. BOOL bRet;
  68. m_sect.Lock();
  69. bRet = CMapPtrToPtr::Lookup(hInternet, (void*&) refpSession);
  70. m_sect.Unlock();
  71. return bRet;
  72. }
  73. };
  74. extern CSessionMapPtrToPtr _afxSessionMap;
  75. /////////////////////////////////////////////////////////////////////////////
  76. // Global Functions
  77. AFX_STATIC BOOL AFXAPI _AfxParseURLWorker(LPCTSTR pstrURL,
  78. LPURL_COMPONENTS lpComponents, DWORD& dwServiceType,
  79. INTERNET_PORT& nPort, DWORD dwFlags)
  80. {
  81. // this function will return bogus stuff if lpComponents
  82. // isn't set up to copy the components
  83. ASSERT(lpComponents != NULL && pstrURL != NULL);
  84. if (lpComponents == NULL || pstrURL == NULL)
  85. return FALSE;
  86. ASSERT(lpComponents->dwHostNameLength == 0 ||
  87. lpComponents->lpszHostName != NULL);
  88. ASSERT(lpComponents->dwUrlPathLength == 0 ||
  89. lpComponents->lpszUrlPath != NULL);
  90. ASSERT(lpComponents->dwUserNameLength == 0 ||
  91. lpComponents->lpszUserName != NULL);
  92. ASSERT(lpComponents->dwPasswordLength == 0 ||
  93. lpComponents->lpszPassword != NULL);
  94. ASSERT(AfxIsValidAddress(lpComponents, sizeof(URL_COMPONENTS), TRUE));
  95. LPTSTR pstrCanonicalizedURL;
  96. TCHAR szCanonicalizedURL[INTERNET_MAX_URL_LENGTH];
  97. DWORD dwNeededLength = INTERNET_MAX_URL_LENGTH;
  98. BOOL bRetVal;
  99. BOOL bMustFree = FALSE;
  100. DWORD dwCanonicalizeFlags = dwFlags &
  101. (ICU_NO_ENCODE | ICU_DECODE | ICU_NO_META |
  102. ICU_ENCODE_SPACES_ONLY | ICU_BROWSER_MODE);
  103. DWORD dwCrackFlags = dwFlags & (ICU_ESCAPE | ICU_USERNAME);
  104. bRetVal = InternetCanonicalizeUrl(pstrURL, szCanonicalizedURL,
  105. &dwNeededLength, dwCanonicalizeFlags);
  106. if (!bRetVal)
  107. {
  108. if (::GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  109. return FALSE;
  110. pstrCanonicalizedURL = new TCHAR[dwNeededLength];
  111. bMustFree = TRUE;
  112. bRetVal = InternetCanonicalizeUrl(pstrURL, pstrCanonicalizedURL,
  113. &dwNeededLength, dwCanonicalizeFlags);
  114. if (!bRetVal)
  115. {
  116. delete [] pstrCanonicalizedURL;
  117. return FALSE;
  118. }
  119. }
  120. else
  121. pstrCanonicalizedURL = szCanonicalizedURL;
  122. // now that it's safely canonicalized, crack it
  123. bRetVal = InternetCrackUrl(pstrCanonicalizedURL, 0,
  124. dwCrackFlags, lpComponents);
  125. if (bMustFree)
  126. delete [] pstrCanonicalizedURL;
  127. // convert to MFC-style service ID
  128. if (!bRetVal)
  129. dwServiceType = AFX_INET_SERVICE_UNK;
  130. else
  131. {
  132. nPort = lpComponents->nPort;
  133. switch (lpComponents->nScheme)
  134. {
  135. case INTERNET_SCHEME_FTP:
  136. dwServiceType = AFX_INET_SERVICE_FTP;
  137. break;
  138. case INTERNET_SCHEME_GOPHER:
  139. dwServiceType = AFX_INET_SERVICE_GOPHER;
  140. break;
  141. case INTERNET_SCHEME_HTTP:
  142. dwServiceType = AFX_INET_SERVICE_HTTP;
  143. break;
  144. case INTERNET_SCHEME_HTTPS:
  145. dwServiceType = AFX_INET_SERVICE_HTTPS;
  146. break;
  147. case INTERNET_SCHEME_FILE:
  148. dwServiceType = AFX_INET_SERVICE_FILE;
  149. break;
  150. case INTERNET_SCHEME_NEWS:
  151. dwServiceType = AFX_INET_SERVICE_NNTP;
  152. break;
  153. case INTERNET_SCHEME_MAILTO:
  154. dwServiceType = AFX_INET_SERVICE_MAILTO;
  155. break;
  156. default:
  157. dwServiceType = AFX_INET_SERVICE_UNK;
  158. }
  159. }
  160. return bRetVal;
  161. }
  162. BOOL AFXAPI AfxParseURLEx(LPCTSTR pstrURL, DWORD& dwServiceType,
  163. CString& strServer, CString& strObject, INTERNET_PORT& nPort,
  164. CString& strUsername, CString& strPassword, DWORD dwFlags/* = 0*/)
  165. {
  166. dwServiceType = AFX_INET_SERVICE_UNK;
  167. ASSERT(pstrURL != NULL);
  168. if (pstrURL == NULL)
  169. return FALSE;
  170. URL_COMPONENTS urlComponents;
  171. memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
  172. urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
  173. urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH;
  174. urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_HOST_NAME_LENGTH+1);
  175. urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH;
  176. urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_PATH_LENGTH+1);
  177. urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH;
  178. urlComponents.lpszUserName = strUsername.GetBuffer(INTERNET_MAX_USER_NAME_LENGTH+1);
  179. urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH;
  180. urlComponents.lpszPassword = strPassword.GetBuffer(INTERNET_MAX_PASSWORD_LENGTH+1);
  181. BOOL bRetVal = _AfxParseURLWorker(pstrURL, &urlComponents,
  182. dwServiceType, nPort, dwFlags);
  183. strServer.ReleaseBuffer();
  184. strObject.ReleaseBuffer();
  185. strUsername.ReleaseBuffer();
  186. strPassword.ReleaseBuffer();
  187. return bRetVal;
  188. }
  189. BOOL AFXAPI AfxParseURL(LPCTSTR pstrURL, DWORD& dwServiceType,
  190. CString& strServer, CString& strObject, INTERNET_PORT& nPort)
  191. {
  192. dwServiceType = AFX_INET_SERVICE_UNK;
  193. ASSERT(pstrURL != NULL);
  194. if (pstrURL == NULL)
  195. return FALSE;
  196. URL_COMPONENTS urlComponents;
  197. memset(&urlComponents, 0, sizeof(URL_COMPONENTS));
  198. urlComponents.dwStructSize = sizeof(URL_COMPONENTS);
  199. urlComponents.dwHostNameLength = INTERNET_MAX_URL_LENGTH;
  200. urlComponents.lpszHostName = strServer.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
  201. urlComponents.dwUrlPathLength = INTERNET_MAX_URL_LENGTH;
  202. urlComponents.lpszUrlPath = strObject.GetBuffer(INTERNET_MAX_URL_LENGTH+1);
  203. BOOL bRetVal = _AfxParseURLWorker(pstrURL, &urlComponents,
  204. dwServiceType, nPort, ICU_BROWSER_MODE);
  205. strServer.ReleaseBuffer();
  206. strObject.ReleaseBuffer();
  207. return bRetVal;
  208. }
  209. DWORD AFXAPI AfxGetInternetHandleType(HINTERNET hQuery)
  210. {
  211. DWORD dwServiceType;
  212. DWORD dwTypeLen = sizeof(dwServiceType);
  213. if (hQuery == NULL ||
  214. !InternetQueryOption(hQuery, INTERNET_OPTION_HANDLE_TYPE,
  215. &dwServiceType, &dwTypeLen))
  216. return AFX_INET_SERVICE_UNK;
  217. else
  218. return dwServiceType;
  219. }
  220. AFX_STATIC BOOL AFXAPI
  221. _AfxQueryCStringInternetOption(HINTERNET hHandle, DWORD dwOption, CString& refString)
  222. {
  223. DWORD dwLength = 0;
  224. LPTSTR pstrBuffer;
  225. if (hHandle == NULL)
  226. return FALSE;
  227. if (!InternetQueryOption(hHandle, dwOption, NULL, &dwLength) &&
  228. GetLastError() != ERROR_INSUFFICIENT_BUFFER)
  229. {
  230. refString.Empty();
  231. return FALSE;
  232. }
  233. pstrBuffer = refString.GetBuffer(dwLength);
  234. BOOL bRet = InternetQueryOption(hHandle, dwOption, pstrBuffer, &dwLength);
  235. refString.ReleaseBuffer();
  236. return bRet;
  237. }
  238. #ifdef _DEBUG
  239. void AFXAPI AfxInternetStatusCallbackDebug(HINTERNET hInternet,
  240. DWORD dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInformation,
  241. DWORD dwStatusInformationLength)
  242. {
  243. UNUSED_ALWAYS(hInternet);
  244. TRACE1("Internet ctxt=%d: ", dwContext);
  245. switch (dwInternetStatus)
  246. {
  247. case INTERNET_STATUS_RESOLVING_NAME:
  248. TRACE1("resolving name for %s\n", lpvStatusInformation);
  249. break;
  250. case INTERNET_STATUS_NAME_RESOLVED:
  251. TRACE1("resolved name for %s!\n", lpvStatusInformation);
  252. break;
  253. case INTERNET_STATUS_HANDLE_CREATED:
  254. TRACE1("handle %8.8X created\n", hInternet);
  255. break;
  256. case INTERNET_STATUS_CONNECTING_TO_SERVER:
  257. {
  258. sockaddr* pSockAddr = (sockaddr*) lpvStatusInformation;
  259. TRACE1("connecting to socket address \"%s\"\n", pSockAddr->sa_data);
  260. }
  261. break;
  262. case INTERNET_STATUS_REQUEST_SENT:
  263. TRACE0("request sent!\n");
  264. break;
  265. case INTERNET_STATUS_SENDING_REQUEST:
  266. TRACE0("sending request...\n");
  267. break;
  268. case INTERNET_STATUS_CONNECTED_TO_SERVER:
  269. TRACE0("connected to socket address!\n");
  270. break;
  271. case INTERNET_STATUS_RECEIVING_RESPONSE:
  272. TRACE0("receiving response...\n");
  273. break;
  274. case INTERNET_STATUS_RESPONSE_RECEIVED:
  275. TRACE0("response received!\n");
  276. break;
  277. case INTERNET_STATUS_CLOSING_CONNECTION:
  278. TRACE1("closing connection %8.8X\n", hInternet);
  279. break;
  280. case INTERNET_STATUS_CONNECTION_CLOSED:
  281. TRACE1("connection %8.8X closed!\n", hInternet);
  282. break;
  283. case INTERNET_STATUS_HANDLE_CLOSING:
  284. TRACE1("handle %8.8X closed!\n", hInternet);
  285. break;
  286. case INTERNET_STATUS_REQUEST_COMPLETE:
  287. if (dwStatusInformationLength == sizeof(INTERNET_ASYNC_RESULT))
  288. {
  289. INTERNET_ASYNC_RESULT* pResult = (INTERNET_ASYNC_RESULT*) lpvStatusInformation;
  290. TRACE2("request complete, dwResult = %8.8X, dwError = %8.8X\n",
  291. pResult->dwResult, pResult->dwError);
  292. }
  293. else
  294. TRACE0("request complete.\n");
  295. break;
  296. case INTERNET_STATUS_CTL_RESPONSE_RECEIVED:
  297. case INTERNET_STATUS_REDIRECT:
  298. default:
  299. TRACE1("Unknown status: %d\n", dwInternetStatus);
  300. break;
  301. }
  302. return;
  303. }
  304. #endif // _DEBUG
  305. void AFXAPI AfxInternetStatusCallback(HINTERNET hInternet, DWORD dwContext,
  306. DWORD dwInternetStatus, LPVOID lpvStatusInformation,
  307. DWORD dwStatusInformationLength)
  308. {
  309. CInternetSession* pSession;
  310. #ifdef _DEBUG
  311. if (afxTraceFlags & traceInternet)
  312. AfxInternetStatusCallbackDebug(hInternet, dwContext,
  313. dwInternetStatus, lpvStatusInformation, dwStatusInformationLength);
  314. #endif
  315. if (_afxSessionMap.Lookup(hInternet, pSession))
  316. {
  317. pSession->OnStatusCallback(dwContext, dwInternetStatus,
  318. lpvStatusInformation, dwStatusInformationLength);
  319. }
  320. // note that an entry we can't match is simply ignored as
  321. // WININET can send notifications for handles that we can't
  322. // see -- such as when using InternetOpenURL()
  323. }
  324. /////////////////////////////////////////////////////////////////////////////
  325. // CInternetSession
  326. CInternetSession::~CInternetSession()
  327. {
  328. Close();
  329. }
  330. CInternetSession::CInternetSession(LPCTSTR pstrAgent /* = NULL */,
  331. DWORD dwContext /* = 1 */,
  332. DWORD dwAccessType /* = PRE_CONFIG_INTERNET_ACCESS */,
  333. LPCTSTR pstrProxyName /* = NULL */,
  334. LPCTSTR pstrProxyBypass /* = NULL */,
  335. DWORD dwFlags /* = 0 */)
  336. {
  337. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  338. m_bCallbackEnabled = FALSE;
  339. m_pOldCallback = NULL;
  340. m_dwContext = dwContext;
  341. if (pstrAgent == NULL)
  342. pstrAgent = AfxGetAppName();
  343. m_hSession = InternetOpen(pstrAgent, dwAccessType,
  344. pstrProxyName, pstrProxyBypass, dwFlags);
  345. if (m_hSession == NULL)
  346. AfxThrowInternetException(m_dwContext);
  347. else
  348. _afxSessionMap.SetAt(m_hSession, this);
  349. }
  350. void CInternetSession::Close()
  351. {
  352. if (m_bCallbackEnabled)
  353. EnableStatusCallback(FALSE);
  354. if (m_hSession != NULL)
  355. {
  356. InternetCloseHandle(m_hSession);
  357. _afxSessionMap.RemoveKey(m_hSession);
  358. m_hSession = NULL;
  359. }
  360. }
  361. CGopherConnection* CInternetSession::GetGopherConnection(LPCTSTR pstrServer,
  362. LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */,
  363. INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
  364. {
  365. ASSERT(AfxIsValidString(pstrServer));
  366. CGopherConnection* pReturn = new CGopherConnection(this,
  367. pstrServer, pstrUserName, pstrPassword, m_dwContext, nPort);
  368. return pReturn;
  369. }
  370. CFtpConnection* CInternetSession::GetFtpConnection(LPCTSTR pstrServer,
  371. LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */,
  372. INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  373. BOOL bPassive /* = FALSE */)
  374. {
  375. ASSERT(AfxIsValidString(pstrServer));
  376. CFtpConnection* pReturn = new CFtpConnection(this,
  377. pstrServer, pstrUserName, pstrPassword, m_dwContext,
  378. nPort, bPassive);
  379. return pReturn;
  380. }
  381. CHttpConnection* CInternetSession::GetHttpConnection(LPCTSTR pstrServer,
  382. INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  383. LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */)
  384. {
  385. ASSERT(AfxIsValidString(pstrServer));
  386. CHttpConnection* pReturn = new CHttpConnection(this,
  387. pstrServer, nPort, pstrUserName, pstrPassword, m_dwContext);
  388. return pReturn;
  389. }
  390. CHttpConnection* CInternetSession::GetHttpConnection(LPCTSTR pstrServer,
  391. DWORD dwFlags, INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  392. LPCTSTR pstrUserName /* = NULL */, LPCTSTR pstrPassword /* = NULL */)
  393. {
  394. ASSERT(AfxIsValidString(pstrServer));
  395. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  396. CHttpConnection* pReturn = new CHttpConnection(this, pstrServer,
  397. dwFlags, nPort, pstrUserName, pstrPassword, m_dwContext);
  398. return pReturn;
  399. }
  400. CStdioFile* CInternetSession::OpenURL(LPCTSTR pstrURL,
  401. DWORD dwContext /* = 0 */, DWORD dwFlags /* = INTERNET_FLAG_TRANSFER_BINARY */,
  402. LPCTSTR pstrHeaders /* = NULL */, DWORD dwHeadersLength /* = 0 */)
  403. {
  404. ASSERT(AfxIsValidString(pstrURL));
  405. ASSERT(dwHeadersLength == 0 || pstrHeaders != NULL);
  406. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  407. // must have TRANSFER_BINARY or TRANSFER_ASCII but not both
  408. #define _AFX_TRANSFER_MASK (INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_TRANSFER_ASCII)
  409. ASSERT((dwFlags & _AFX_TRANSFER_MASK) != 0);
  410. ASSERT((dwFlags & _AFX_TRANSFER_MASK) != _AFX_TRANSFER_MASK);
  411. if (dwContext == 1)
  412. dwContext = m_dwContext;
  413. DWORD dwServiceType;
  414. CString strServer;
  415. CString strObject;
  416. INTERNET_PORT nPort;
  417. CStdioFile* pReturn;
  418. BOOL bParsed = AfxParseURL(pstrURL, dwServiceType, strServer, strObject, nPort);
  419. // if it turns out to be a file...
  420. if (bParsed && dwServiceType == AFX_INET_SERVICE_FILE)
  421. {
  422. int nMode = CFile::modeRead | CFile::shareCompat;
  423. if (dwFlags & INTERNET_FLAG_TRANSFER_BINARY)
  424. nMode |= CFile::typeBinary;
  425. else
  426. nMode |= CFile::typeText;
  427. pReturn = new CStdioFile(strObject, nMode);
  428. }
  429. else
  430. {
  431. HINTERNET hOpener;
  432. hOpener = InternetOpenUrl(m_hSession, pstrURL, pstrHeaders,
  433. dwHeadersLength, dwFlags, dwContext);
  434. if (hOpener == NULL)
  435. AfxThrowInternetException(m_dwContext);
  436. if (!bParsed)
  437. dwServiceType = AfxGetInternetHandleType(hOpener);
  438. switch (dwServiceType)
  439. {
  440. case INTERNET_HANDLE_TYPE_GOPHER_FILE:
  441. case AFX_INET_SERVICE_GOPHER:
  442. //WINBUG: WININET supplies no way to
  443. // convert from a URL to a Gopher locator
  444. pReturn = new CGopherFile(hOpener, m_hSession, _T(""),
  445. 0, dwContext);
  446. _afxSessionMap.SetAt(hOpener, this);
  447. break;
  448. case INTERNET_HANDLE_TYPE_FTP_FILE:
  449. case AFX_INET_SERVICE_FTP:
  450. pReturn = new CInternetFile(hOpener, m_hSession, strObject,
  451. strServer, dwContext, TRUE);
  452. _afxSessionMap.SetAt(hOpener, this);
  453. break;
  454. case INTERNET_HANDLE_TYPE_HTTP_REQUEST:
  455. case AFX_INET_SERVICE_HTTP:
  456. case AFX_INET_SERVICE_HTTPS:
  457. pReturn = new CHttpFile(hOpener, m_hSession, strObject, strServer,
  458. CHttpConnection::szHtmlVerbs[CHttpConnection::HTTP_VERB_GET],
  459. dwContext);
  460. _afxSessionMap.SetAt(hOpener, this);
  461. break;
  462. default:
  463. TRACE1("Error: Unidentified service type: %8.8X\n", dwServiceType);
  464. pReturn = NULL;
  465. }
  466. }
  467. return pReturn;
  468. }
  469. BOOL CInternetSession::SetOption(DWORD dwOption, LPVOID lpBuffer,
  470. DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
  471. {
  472. ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
  473. ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  474. dwOption <= INTERNET_LAST_OPTION);
  475. ASSERT(dwBufferLength != 0);
  476. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  477. // bogus flag?
  478. ASSERT(dwFlags == 0 || ((dwFlags & ISO_VALID_FLAGS) == dwFlags));
  479. return InternetSetOptionEx(m_hSession, dwOption,
  480. lpBuffer, dwBufferLength, dwFlags);
  481. }
  482. BOOL CInternetSession::QueryOption(DWORD dwOption, LPVOID lpBuffer,
  483. LPDWORD lpdwBufferLength) const
  484. {
  485. ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  486. dwOption <= INTERNET_LAST_OPTION);
  487. ASSERT_POINTER(lpdwBufferLength, DWORD);
  488. ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
  489. ASSERT(*lpdwBufferLength != 0);
  490. return InternetQueryOption(m_hSession, dwOption,
  491. lpBuffer, lpdwBufferLength);
  492. }
  493. BOOL CInternetSession::QueryOption(DWORD dwOption, DWORD& dwValue) const
  494. {
  495. DWORD dwLen = sizeof(DWORD);
  496. return InternetQueryOption(m_hSession, dwOption,
  497. &dwValue, &dwLen);
  498. }
  499. BOOL CInternetSession::QueryOption(DWORD dwOption, CString& refString) const
  500. {
  501. ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  502. dwOption <= INTERNET_LAST_OPTION);
  503. return _AfxQueryCStringInternetOption(m_hSession, dwOption, refString);
  504. }
  505. void CInternetSession::OnStatusCallback(DWORD dwContext,
  506. DWORD dwInternetStatus, LPVOID lpvStatusInformation,
  507. DWORD dwStatusInformationLength)
  508. {
  509. ASSERT(m_bCallbackEnabled != NULL);
  510. if (m_pOldCallback != NULL)
  511. {
  512. (*m_pOldCallback)(m_hSession, dwContext, dwInternetStatus,
  513. lpvStatusInformation, dwStatusInformationLength);
  514. }
  515. }
  516. BOOL CInternetSession::EnableStatusCallback(BOOL bEnable /* = TRUE */)
  517. {
  518. ASSERT(!bEnable || m_hSession != NULL);
  519. if (m_hSession == NULL)
  520. return FALSE;
  521. BOOL bResult = TRUE;
  522. if (bEnable)
  523. {
  524. ASSERT(!m_bCallbackEnabled);
  525. if (!m_bCallbackEnabled)
  526. {
  527. INTERNET_STATUS_CALLBACK pRet =
  528. InternetSetStatusCallback(m_hSession, AfxInternetStatusCallback);
  529. if (pRet != INTERNET_INVALID_STATUS_CALLBACK)
  530. {
  531. m_pOldCallback = pRet;
  532. m_bCallbackEnabled = TRUE;
  533. }
  534. else
  535. AfxThrowInternetException(m_dwContext);
  536. }
  537. }
  538. else
  539. {
  540. ASSERT(m_bCallbackEnabled);
  541. if (m_bCallbackEnabled)
  542. {
  543. InternetSetStatusCallback(m_hSession, NULL);
  544. m_bCallbackEnabled = FALSE;
  545. }
  546. }
  547. return bResult;
  548. }
  549. BOOL CInternetSession::SetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, LPCTSTR pstrCookieData)
  550. {
  551. AfxThrowInternetException(GetLastError());
  552. return false;
  553. }
  554. BOOL CInternetSession::GetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, LPTSTR pstrCookieData, DWORD dwBufLen)
  555. {
  556. AfxThrowInternetException(GetLastError());
  557. return false;
  558. }
  559. DWORD CInternetSession::GetCookieLength(LPCSTR pstrUrl, LPCTSTR pstrCookieName)
  560. {
  561. AfxThrowInternetException(GetLastError());
  562. return 0;
  563. }
  564. BOOL CInternetSession::GetCookie(LPCSTR pstrUrl, LPCTSTR pstrCookieName, CString& strCookieData)
  565. {
  566. AfxThrowInternetException(GetLastError());
  567. return false;
  568. }
  569. #ifdef _DEBUG
  570. void CInternetSession::Dump(CDumpContext& dc) const
  571. {
  572. CObject::Dump(dc);
  573. dc << "m_hSession = " << m_hSession;
  574. dc << "\nm_dwContext = " << m_dwContext;
  575. }
  576. #endif
  577. /////////////////////////////////////////////////////////////////////////////
  578. // Internet Files
  579. CInternetFile::CInternetFile(HINTERNET hFile, HINTERNET /* hSession */,
  580. LPCTSTR pstrFileName, LPCTSTR pstrServer, DWORD dwContext, BOOL bReadMode)
  581. : m_dwContext(dwContext)
  582. {
  583. // caller must set _afxSessionMap()!
  584. ASSERT(AfxIsValidString(pstrServer));
  585. ASSERT(AfxIsValidString(pstrFileName));
  586. ASSERT(hFile != NULL);
  587. m_strFileName = pstrFileName;
  588. m_strServerName = pstrServer;
  589. m_hFile = hFile;
  590. m_bReadMode = bReadMode;
  591. m_pbReadBuffer = NULL;
  592. m_pbWriteBuffer = NULL;
  593. m_nReadBufferSize = 0;
  594. m_nReadBufferPos = 0;
  595. m_nWriteBufferSize = 0;
  596. m_nWriteBufferPos = 0;
  597. m_nReadBufferBytes = 0;
  598. }
  599. CInternetFile::CInternetFile(HINTERNET hFile,
  600. LPCTSTR pstrFileName, CInternetConnection* pConnection, BOOL bReadMode)
  601. {
  602. ASSERT(AfxIsValidString(pstrFileName));
  603. ASSERT(pConnection != NULL);
  604. ASSERT_VALID(pConnection);
  605. ASSERT(hFile != NULL);
  606. _afxSessionMap.SetAt(hFile, pConnection->GetSession());
  607. m_strFileName = pstrFileName;
  608. m_dwContext = pConnection->GetContext();
  609. m_strServerName = pConnection->GetServerName();
  610. m_hFile = hFile;
  611. m_bReadMode = bReadMode;
  612. m_pbReadBuffer = NULL;
  613. m_pbWriteBuffer = NULL;
  614. m_nReadBufferSize = 0;
  615. m_nReadBufferPos = 0;
  616. m_nWriteBufferSize = 0;
  617. m_nWriteBufferPos = 0;
  618. m_nReadBufferBytes = 0;
  619. }
  620. BOOL CInternetFile::QueryOption(DWORD dwOption, LPVOID lpBuffer,
  621. LPDWORD lpdwBufferLength) const
  622. {
  623. ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  624. dwOption <= INTERNET_LAST_OPTION);
  625. ASSERT_POINTER(lpdwBufferLength, DWORD);
  626. ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
  627. ASSERT(*lpdwBufferLength != 0);
  628. ASSERT(m_hFile != NULL);
  629. return InternetQueryOption(m_hFile, dwOption,
  630. lpBuffer, lpdwBufferLength);
  631. }
  632. BOOL CInternetFile::QueryOption(DWORD dwOption, DWORD& dwValue) const
  633. {
  634. ASSERT(m_hFile != NULL);
  635. DWORD dwLen = sizeof(DWORD);
  636. return InternetQueryOption(m_hFile, dwOption,
  637. &dwValue, &dwLen);
  638. }
  639. BOOL CInternetFile::QueryOption(DWORD dwOption, CString& refString) const
  640. {
  641. ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  642. dwOption <= INTERNET_LAST_OPTION);
  643. ASSERT(m_hFile != NULL);
  644. return _AfxQueryCStringInternetOption(m_hFile, dwOption, refString);
  645. }
  646. BOOL CInternetFile::SetOption(DWORD dwOption, LPVOID lpBuffer,
  647. DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
  648. {
  649. ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  650. dwOption <= INTERNET_LAST_OPTION);
  651. ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
  652. ASSERT(dwBufferLength != 0);
  653. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  654. // bogus flag?
  655. ASSERT(dwFlags == 0 || ((dwFlags & ISO_VALID_FLAGS) == dwFlags));
  656. return InternetSetOptionEx(m_hFile, dwOption,
  657. lpBuffer, dwBufferLength, dwFlags);
  658. }
  659. BOOL CInternetFile::SetReadBufferSize(UINT nReadSize)
  660. {
  661. ASSERT_VALID(this);
  662. BOOL bRet = TRUE;
  663. if (nReadSize != -1 && nReadSize != m_nReadBufferSize)
  664. {
  665. if (m_nReadBufferPos > nReadSize)
  666. bRet = FALSE;
  667. else
  668. {
  669. if (nReadSize == 0)
  670. {
  671. delete [] m_pbReadBuffer;
  672. m_pbReadBuffer = NULL;
  673. }
  674. else if (m_pbReadBuffer == NULL)
  675. {
  676. m_pbReadBuffer = new BYTE[nReadSize];
  677. m_nReadBufferPos = nReadSize;
  678. }
  679. else
  680. {
  681. DWORD dwMoved = m_nReadBufferSize - m_nReadBufferPos;
  682. LPBYTE pbTemp = m_pbReadBuffer;
  683. m_pbReadBuffer = new BYTE[nReadSize];
  684. if (dwMoved > 0)
  685. {
  686. memcpy(m_pbReadBuffer, pbTemp + m_nReadBufferPos, dwMoved);
  687. m_nReadBufferPos = 0;
  688. m_nReadBufferBytes = dwMoved;
  689. }
  690. else
  691. {
  692. m_nReadBufferBytes = 0;
  693. m_nReadBufferPos = nReadSize;
  694. }
  695. delete [] pbTemp;
  696. }
  697. m_nReadBufferSize = nReadSize;
  698. }
  699. }
  700. return bRet;
  701. }
  702. BOOL CInternetFile::SetWriteBufferSize(UINT nWriteSize)
  703. {
  704. ASSERT_VALID(this);
  705. BOOL bRet = TRUE;
  706. if (nWriteSize != m_nWriteBufferSize)
  707. {
  708. if (m_nWriteBufferPos > nWriteSize)
  709. Flush();
  710. if (nWriteSize == 0)
  711. {
  712. delete [] m_pbWriteBuffer;
  713. m_pbWriteBuffer = NULL;
  714. }
  715. else if (m_pbWriteBuffer == NULL)
  716. {
  717. m_pbWriteBuffer = new BYTE[nWriteSize];
  718. m_nWriteBufferPos = 0;
  719. }
  720. else
  721. {
  722. LPBYTE pbTemp = m_pbWriteBuffer;
  723. m_pbWriteBuffer = new BYTE[nWriteSize];
  724. memcpy(m_pbWriteBuffer, pbTemp, m_nWriteBufferPos);
  725. delete [] pbTemp;
  726. }
  727. m_nWriteBufferSize = nWriteSize;
  728. }
  729. return bRet;
  730. }
  731. LONG CInternetFile::Seek(LONG lOffset, UINT nFrom)
  732. {
  733. ASSERT_VALID(this);
  734. ASSERT(m_hFile != NULL);
  735. ASSERT(m_bReadMode);
  736. ASSERT(m_pbReadBuffer == NULL);
  737. // can't do this on a file for writing
  738. // can't do this on a file that's got a buffer
  739. if (!m_bReadMode || m_pbReadBuffer != NULL)
  740. AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  741. switch (nFrom)
  742. {
  743. case begin:
  744. nFrom = FILE_BEGIN;
  745. break;
  746. case current:
  747. nFrom = FILE_CURRENT;
  748. break;
  749. case end:
  750. nFrom = FILE_END;
  751. break;
  752. default:
  753. ASSERT(FALSE); // got a bogus nFrom value
  754. AfxThrowInternetException(m_dwContext, ERROR_INVALID_PARAMETER);
  755. break;
  756. }
  757. LONG lRet;
  758. lRet = InternetSetFilePointer(m_hFile, lOffset, NULL, nFrom, m_dwContext);
  759. if (lRet == -1)
  760. AfxThrowInternetException(m_dwContext);
  761. return lRet;
  762. }
  763. CInternetFile::~CInternetFile()
  764. {
  765. if (m_hFile != NULL)
  766. {
  767. #ifdef _DEBUG
  768. USES_CONVERSION;
  769. LPCTSTR pszName = A2CT(GetRuntimeClass()->m_lpszClassName);
  770. TRACE2("Warning: destroying an open %s with handle %8.8X\n",
  771. pszName, m_hFile);
  772. #endif
  773. Close();
  774. }
  775. if (m_pbReadBuffer != NULL)
  776. delete m_pbReadBuffer;
  777. if (m_pbWriteBuffer != NULL)
  778. delete m_pbWriteBuffer;
  779. }
  780. void CInternetFile::Abort()
  781. {
  782. ASSERT_VALID(this);
  783. if (m_hFile != NULL)
  784. Close();
  785. m_strFileName.Empty();
  786. }
  787. void CInternetFile::Flush()
  788. {
  789. if (m_pbWriteBuffer != NULL && m_nWriteBufferPos > 0)
  790. {
  791. DWORD dwBytes;
  792. if (!InternetWriteFile(m_hFile, m_pbWriteBuffer,
  793. m_nWriteBufferPos, &dwBytes))
  794. AfxThrowInternetException(m_dwContext);
  795. if (dwBytes != m_nWriteBufferPos)
  796. AfxThrowInternetException(m_dwContext);
  797. m_nWriteBufferPos = 0;
  798. }
  799. }
  800. void CInternetFile::Close()
  801. {
  802. if (m_hFile != NULL)
  803. {
  804. Flush();
  805. InternetCloseHandle(m_hFile);
  806. _afxSessionMap.RemoveKey(m_hFile);
  807. m_hFile = NULL;
  808. if (m_pbWriteBuffer != NULL)
  809. {
  810. delete [] m_pbWriteBuffer;
  811. m_pbWriteBuffer = NULL;
  812. }
  813. if (m_pbReadBuffer != NULL)
  814. {
  815. delete [] m_pbReadBuffer;
  816. m_pbReadBuffer = NULL;
  817. }
  818. }
  819. }
  820. UINT CInternetFile::Read(LPVOID lpBuf, UINT nCount)
  821. {
  822. ASSERT_VALID(this);
  823. ASSERT(AfxIsValidAddress(lpBuf, nCount));
  824. ASSERT(m_hFile != NULL);
  825. ASSERT(m_bReadMode);
  826. DWORD dwBytes;
  827. if (!m_bReadMode || m_hFile == NULL)
  828. AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  829. if (m_pbReadBuffer == NULL)
  830. {
  831. if (!InternetReadFile(m_hFile, (LPVOID) lpBuf, nCount, &dwBytes))
  832. AfxThrowInternetException(m_dwContext);
  833. return dwBytes;
  834. }
  835. LPBYTE lpbBuf = (LPBYTE) lpBuf;
  836. // if the requested size is bigger than our buffer,
  837. // then handle it directly
  838. if (nCount >= m_nReadBufferSize)
  839. {
  840. DWORD dwMoved = max(0, (long)m_nReadBufferBytes - (long)m_nReadBufferPos);
  841. memcpy(lpBuf, m_pbReadBuffer + m_nReadBufferPos, dwMoved);
  842. m_nReadBufferPos = m_nReadBufferSize;
  843. if (!InternetReadFile(m_hFile, lpbBuf+dwMoved, nCount-dwMoved, &dwBytes))
  844. AfxThrowInternetException(m_dwContext);
  845. dwBytes += dwMoved;
  846. }
  847. else
  848. {
  849. if (m_nReadBufferPos + nCount >= m_nReadBufferBytes)
  850. {
  851. DWORD dwMoved = max(0, (long)m_nReadBufferBytes - (long)m_nReadBufferPos);
  852. memcpy(lpbBuf, m_pbReadBuffer + m_nReadBufferPos, dwMoved);
  853. DWORD dwRead;
  854. if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
  855. &dwRead))
  856. AfxThrowInternetException(m_dwContext);
  857. m_nReadBufferBytes = dwRead;
  858. dwRead = min(nCount - dwMoved, m_nReadBufferBytes);
  859. memcpy(lpbBuf + dwMoved, m_pbReadBuffer, dwRead);
  860. m_nReadBufferPos = dwRead;
  861. dwBytes = dwMoved + dwRead;
  862. }
  863. else
  864. {
  865. memcpy(lpbBuf, m_pbReadBuffer + m_nReadBufferPos, nCount);
  866. m_nReadBufferPos += nCount;
  867. dwBytes = nCount;
  868. }
  869. }
  870. return dwBytes;
  871. }
  872. void CInternetFile::Write(const void* lpBuf, UINT nCount)
  873. {
  874. ASSERT_VALID(this);
  875. ASSERT(m_hFile != NULL);
  876. ASSERT(AfxIsValidAddress(lpBuf, nCount, FALSE));
  877. ASSERT(m_bReadMode == FALSE || m_bReadMode == -1);
  878. if (m_bReadMode == TRUE || m_hFile == NULL)
  879. AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  880. DWORD dwBytes;
  881. if (m_pbWriteBuffer == NULL)
  882. {
  883. if (!InternetWriteFile(m_hFile, lpBuf, nCount, &dwBytes))
  884. AfxThrowInternetException(m_dwContext);
  885. if (dwBytes != nCount)
  886. AfxThrowInternetException(m_dwContext);
  887. }
  888. else
  889. {
  890. if ((m_nWriteBufferPos + nCount) >= m_nWriteBufferSize)
  891. {
  892. // write what is in the buffer just now
  893. if (!InternetWriteFile(m_hFile, m_pbWriteBuffer,
  894. m_nWriteBufferPos, &dwBytes))
  895. AfxThrowInternetException(m_dwContext);
  896. // reset the buffer position since it is now clean
  897. m_nWriteBufferPos = 0;
  898. }
  899. // if we can't hope to buffer the write request,
  900. // do it immediately ... otherwise, buffer it!
  901. if (nCount >= m_nWriteBufferSize)
  902. {
  903. if (!InternetWriteFile(m_hFile, (LPVOID) lpBuf, nCount, &dwBytes))
  904. AfxThrowInternetException(m_dwContext);
  905. }
  906. else
  907. {
  908. memcpy(m_nWriteBufferPos + m_pbWriteBuffer, lpBuf, nCount);
  909. m_nWriteBufferPos += nCount;
  910. }
  911. }
  912. }
  913. void CInternetFile::WriteString(LPCTSTR pstr)
  914. {
  915. ASSERT(m_bReadMode == TRUE || m_bReadMode == -1);
  916. ASSERT(AfxIsValidString(pstr));
  917. ASSERT_VALID(this);
  918. ASSERT(m_hFile != NULL);
  919. if (m_bReadMode == TRUE)
  920. AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  921. Write(pstr, lstrlen(pstr));
  922. }
  923. LPTSTR CInternetFile::ReadString(LPTSTR pstr, UINT nMax)
  924. {
  925. ASSERT_VALID(this);
  926. ASSERT(m_hFile != NULL);
  927. ASSERT(AfxIsValidAddress(pstr, nMax*sizeof(TCHAR)));
  928. DWORD dwRead;
  929. // if we're reading line-by-line, we must have a buffer
  930. if (m_pbReadBuffer == NULL)
  931. {
  932. if (!SetReadBufferSize(4096)) // arbitrary but reasonable
  933. return NULL;
  934. if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
  935. &dwRead))
  936. AfxThrowInternetException(m_dwContext);
  937. m_nReadBufferBytes = dwRead;
  938. m_nReadBufferPos = 0;
  939. }
  940. LPTSTR pstrChar = (LPTSTR) (m_pbReadBuffer + m_nReadBufferPos);
  941. LPTSTR pstrTarget = pstr;
  942. while (--nMax)
  943. {
  944. if (m_nReadBufferPos >= m_nReadBufferBytes)
  945. {
  946. if (!InternetReadFile(m_hFile, m_pbReadBuffer, m_nReadBufferSize,
  947. &dwRead))
  948. AfxThrowInternetException(m_dwContext);
  949. m_nReadBufferBytes = dwRead;
  950. if (m_nReadBufferBytes == 0)
  951. {
  952. *pstrTarget = '\0';
  953. if (pstrTarget == pstr)
  954. return NULL;
  955. else
  956. return pstr;
  957. }
  958. else
  959. {
  960. m_nReadBufferPos = 0;
  961. pstrChar = (LPTSTR) m_pbReadBuffer;
  962. }
  963. }
  964. if (*pstrChar != '\r')
  965. *pstrTarget++ = *pstrChar;
  966. m_nReadBufferPos++;
  967. if (*pstrChar++ == '\n')
  968. break;
  969. }
  970. *pstrTarget = '\0';
  971. return pstr;
  972. }
  973. BOOL CInternetFile::ReadString(CString& rString)
  974. {
  975. ASSERT_VALID(this);
  976. ASSERT(m_hFile != NULL);
  977. rString = _T(""); // empty string without deallocating
  978. const int nMaxSize = 128;
  979. LPTSTR pstrPlace = rString.GetBuffer(nMaxSize);
  980. LPTSTR pstrResult;
  981. int nLen;
  982. do
  983. {
  984. pstrResult = ReadString(pstrPlace, nMaxSize);
  985. rString.ReleaseBuffer();
  986. // if string is read completely or EOF
  987. if (pstrResult == NULL ||
  988. (nLen = lstrlen(pstrPlace)) < (nMaxSize-1) ||
  989. pstrPlace[nLen-1] == '\n')
  990. break;
  991. nLen = rString.GetLength();
  992. pstrPlace = rString.GetBuffer(nMaxSize + nLen) + nLen;
  993. } while (1);
  994. // remove '\n' from end of string if present
  995. pstrPlace = rString.GetBuffer(0);
  996. nLen = rString.GetLength();
  997. if (nLen != 0 && pstrPlace[nLen-1] == '\n')
  998. pstrPlace[nLen-1] = '\0';
  999. rString.ReleaseBuffer();
  1000. return (pstrResult != NULL);
  1001. }
  1002. DWORD CInternetFile::GetLength() const
  1003. {
  1004. ASSERT_VALID(this);
  1005. ASSERT(m_hFile != NULL);
  1006. DWORD dwRet = 0;
  1007. if (m_hFile != NULL)
  1008. {
  1009. if (!InternetQueryDataAvailable(m_hFile, &dwRet, 0, 0))
  1010. dwRet = 0;
  1011. }
  1012. return dwRet;
  1013. }
  1014. void CInternetFile::LockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  1015. {
  1016. ASSERT_VALID(this);
  1017. ASSERT(m_hFile != NULL);
  1018. AfxThrowNotSupportedException();
  1019. }
  1020. void CInternetFile::UnlockRange(DWORD /* dwPos */, DWORD /* dwCount */)
  1021. {
  1022. ASSERT_VALID(this);
  1023. ASSERT(m_hFile != NULL);
  1024. AfxThrowNotSupportedException();
  1025. }
  1026. void CInternetFile::SetLength(DWORD)
  1027. {
  1028. ASSERT_VALID(this);
  1029. ASSERT(m_hFile != NULL);
  1030. AfxThrowNotSupportedException();
  1031. }
  1032. CFile* CInternetFile::Duplicate() const
  1033. {
  1034. ASSERT_VALID(this);
  1035. ASSERT(m_pStream != NULL);
  1036. AfxThrowNotSupportedException();
  1037. return NULL;
  1038. }
  1039. #ifdef _DEBUG
  1040. void CInternetFile::AssertValid() const
  1041. {
  1042. // Don't call CStdioFile's AsssertValid()
  1043. CFile::AssertValid();
  1044. ASSERT(m_hConnection != NULL);
  1045. // make sure we really have a decent handle
  1046. if (m_hFile != NULL)
  1047. {
  1048. DWORD dwResult = AfxGetInternetHandleType(m_hFile);
  1049. if (IsKindOf(RUNTIME_CLASS(CHttpFile)))
  1050. {
  1051. ASSERT(dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
  1052. }
  1053. else if (IsKindOf(RUNTIME_CLASS(CGopherFile)))
  1054. {
  1055. ASSERT(dwResult == INTERNET_HANDLE_TYPE_GOPHER_FILE ||
  1056. dwResult == INTERNET_HANDLE_TYPE_GOPHER_FIND_HTML ||
  1057. dwResult == INTERNET_HANDLE_TYPE_GOPHER_FILE_HTML ||
  1058. dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
  1059. }
  1060. else if (IsKindOf(RUNTIME_CLASS(CInternetFile)))
  1061. {
  1062. ASSERT(dwResult == INTERNET_HANDLE_TYPE_FTP_FILE ||
  1063. dwResult == INTERNET_HANDLE_TYPE_FTP_FILE_HTML ||
  1064. dwResult == INTERNET_HANDLE_TYPE_FTP_FIND_HTML ||
  1065. dwResult == INTERNET_HANDLE_TYPE_HTTP_REQUEST);
  1066. }
  1067. else
  1068. ASSERT(FALSE); // some bogus object!
  1069. }
  1070. }
  1071. void CInternetFile::Dump(CDumpContext& dc) const
  1072. {
  1073. CObject::Dump(dc);
  1074. dc << "\na " << GetRuntimeClass()->m_lpszClassName;
  1075. dc << " with handle " << (UINT)m_hFile;
  1076. }
  1077. #endif
  1078. /////////////////////////////////////////////////////////////////////////////
  1079. // CInternetConnection
  1080. CInternetConnection::CInternetConnection(CInternetSession* pSession,
  1081. LPCTSTR pstrServerName,
  1082. INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1083. DWORD dwContext /* = 1 */)
  1084. : m_strServerName(pstrServerName)
  1085. {
  1086. ASSERT(pSession != NULL);
  1087. ASSERT_VALID(pSession);
  1088. ASSERT(pstrServerName != NULL);
  1089. m_nPort = nPort;
  1090. m_pSession = pSession;
  1091. m_hConnection = NULL;
  1092. if (dwContext == 1)
  1093. dwContext = pSession->GetContext();
  1094. m_dwContext = dwContext;
  1095. }
  1096. CInternetConnection::~CInternetConnection()
  1097. {
  1098. if (m_hConnection != NULL)
  1099. {
  1100. #ifdef _DEBUG
  1101. USES_CONVERSION;
  1102. LPCTSTR pszName = A2CT(GetRuntimeClass()->m_lpszClassName);
  1103. TRACE3("Warning: Disconnecting %s handle %8.8X in context %8.8X at destruction.\n",
  1104. pszName, m_hConnection, m_dwContext);
  1105. #endif
  1106. Close();
  1107. }
  1108. }
  1109. BOOL CInternetConnection::SetOption(DWORD dwOption, LPVOID lpBuffer,
  1110. DWORD dwBufferLength, DWORD dwFlags /* = 0 */)
  1111. {
  1112. ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  1113. dwOption <= INTERNET_LAST_OPTION);
  1114. ASSERT(AfxIsValidAddress(lpBuffer, dwBufferLength, FALSE));
  1115. ASSERT(dwBufferLength != 0);
  1116. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1117. // bogus flag?
  1118. ASSERT(dwFlags == 0 || ((dwFlags & ISO_VALID_FLAGS) == dwFlags));
  1119. return InternetSetOptionEx(m_hConnection, dwOption,
  1120. lpBuffer, dwBufferLength, dwFlags);
  1121. }
  1122. BOOL CInternetConnection::QueryOption(DWORD dwOption, LPVOID lpBuffer,
  1123. LPDWORD lpdwBufferLength) const
  1124. {
  1125. ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  1126. dwOption <= INTERNET_LAST_OPTION);
  1127. ASSERT_POINTER(lpdwBufferLength, DWORD);
  1128. ASSERT(AfxIsValidAddress(lpBuffer, *lpdwBufferLength));
  1129. ASSERT(*lpdwBufferLength != 0);
  1130. return InternetQueryOption(m_hConnection, dwOption,
  1131. lpBuffer, lpdwBufferLength);
  1132. }
  1133. BOOL CInternetConnection::QueryOption(DWORD dwOption, DWORD& dwValue) const
  1134. {
  1135. DWORD dwLen = sizeof(DWORD);
  1136. return InternetQueryOption(m_hConnection, dwOption,
  1137. &dwValue, &dwLen);
  1138. }
  1139. BOOL CInternetConnection::QueryOption(DWORD dwOption, CString& refString) const
  1140. {
  1141. ASSERT(dwOption >= INTERNET_FIRST_OPTION &&
  1142. dwOption <= INTERNET_LAST_OPTION);
  1143. return _AfxQueryCStringInternetOption(m_hConnection, dwOption, refString);
  1144. }
  1145. void CInternetConnection::Close()
  1146. {
  1147. if (m_hConnection != NULL)
  1148. {
  1149. InternetCloseHandle(m_hConnection);
  1150. _afxSessionMap.RemoveKey(m_hConnection);
  1151. m_hConnection = NULL;
  1152. }
  1153. }
  1154. #ifdef _DEBUG
  1155. void CInternetConnection::Dump(CDumpContext& dc) const
  1156. {
  1157. CObject::Dump(dc);
  1158. dc << "m_hConnection = " << m_hConnection;
  1159. }
  1160. void CInternetConnection::AssertValid() const
  1161. {
  1162. CObject::AssertValid();
  1163. }
  1164. #endif
  1165. /////////////////////////////////////////////////////////////////////////////
  1166. // CFtpConnection
  1167. CFtpConnection::~CFtpConnection()
  1168. {
  1169. }
  1170. CFtpConnection::CFtpConnection(CInternetSession* pSession,
  1171. HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext)
  1172. : CInternetConnection(pSession, pstrServer, INTERNET_INVALID_PORT_NUMBER,
  1173. dwContext)
  1174. {
  1175. ASSERT(pSession != NULL);
  1176. ASSERT(AfxIsValidString(pstrServer));
  1177. BOOL bBadType = FALSE;
  1178. if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_FTP)
  1179. {
  1180. ASSERT(FALSE); // used the wrong handle type
  1181. bBadType = TRUE;
  1182. }
  1183. m_strServerName = pstrServer;
  1184. m_hConnection = hConnected;
  1185. if (m_hConnection == NULL || bBadType)
  1186. AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1187. else
  1188. _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1189. }
  1190. CFtpConnection::CFtpConnection(CInternetSession* pSession,
  1191. LPCTSTR pstrServer, LPCTSTR pstrUserName /* = NULL */,
  1192. LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 0 */,
  1193. INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1194. BOOL bPassive /* = FALSE */)
  1195. : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1196. {
  1197. ASSERT(pSession != NULL);
  1198. ASSERT_KINDOF(CInternetSession, pSession);
  1199. ASSERT(AfxIsValidString(pstrServer));
  1200. m_strServerName = pstrServer;
  1201. m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1202. nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_FTP,
  1203. (bPassive ? INTERNET_FLAG_PASSIVE : 0), m_dwContext);
  1204. if (m_hConnection == NULL)
  1205. AfxThrowInternetException(m_dwContext, ::GetLastError());
  1206. else
  1207. _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1208. }
  1209. void CFtpConnection::Close()
  1210. {
  1211. CInternetConnection::Close();
  1212. }
  1213. BOOL CFtpConnection::Remove(LPCTSTR pstrFileName)
  1214. {
  1215. ASSERT_VALID(this);
  1216. ASSERT(m_hConnection != NULL);
  1217. ASSERT(AfxIsValidString(pstrFileName));
  1218. return FtpDeleteFile(m_hConnection, pstrFileName);
  1219. }
  1220. BOOL CFtpConnection::Rename(LPCTSTR pstrExisting, LPCTSTR pstrNew)
  1221. {
  1222. ASSERT_VALID(this);
  1223. ASSERT(m_hConnection != NULL);
  1224. ASSERT(AfxIsValidString(pstrExisting));
  1225. ASSERT(AfxIsValidString(pstrNew));
  1226. return FtpRenameFile(m_hConnection, pstrExisting, pstrNew);
  1227. }
  1228. BOOL CFtpConnection::CreateDirectory(LPCTSTR pstrDirName)
  1229. {
  1230. ASSERT_VALID(this);
  1231. ASSERT(m_hConnection != NULL);
  1232. ASSERT(AfxIsValidString(pstrDirName));
  1233. return FtpCreateDirectory(m_hConnection, pstrDirName);
  1234. }
  1235. BOOL CFtpConnection::RemoveDirectory(LPCTSTR pstrDirName)
  1236. {
  1237. ASSERT_VALID(this);
  1238. ASSERT(m_hConnection != NULL);
  1239. ASSERT(AfxIsValidString(pstrDirName));
  1240. return FtpRemoveDirectory(m_hConnection, pstrDirName);
  1241. }
  1242. BOOL CFtpConnection::SetCurrentDirectory(LPCTSTR pstrDirName)
  1243. {
  1244. ASSERT_VALID(this);
  1245. ASSERT(m_hConnection != NULL);
  1246. ASSERT(AfxIsValidString(pstrDirName));
  1247. return FtpSetCurrentDirectory(m_hConnection, pstrDirName);
  1248. }
  1249. BOOL CFtpConnection::GetCurrentDirectory(LPTSTR pstrDirName,
  1250. LPDWORD lpdwLen) const
  1251. {
  1252. ASSERT_VALID(this);
  1253. ASSERT(m_hConnection != NULL);
  1254. ASSERT(AfxIsValidAddress(pstrDirName, *lpdwLen));
  1255. ASSERT(lpdwLen != 0);
  1256. return FtpGetCurrentDirectory(m_hConnection, pstrDirName, lpdwLen);
  1257. }
  1258. BOOL CFtpConnection::GetCurrentDirectoryAsURL(CString& strDirName) const
  1259. {
  1260. CString strDirectory;
  1261. if (!GetCurrentDirectory(strDirectory))
  1262. return FALSE;
  1263. strDirName = _afxURLftp;
  1264. strDirName += GetServerName();
  1265. if (strDirectory[0] != '/')
  1266. strDirName += '/';
  1267. strDirName += strDirectory;
  1268. return TRUE;
  1269. }
  1270. BOOL CFtpConnection::GetCurrentDirectoryAsURL(LPTSTR pstrName,
  1271. LPDWORD lpdwLen) const
  1272. {
  1273. ASSERT(lpdwLen != NULL);
  1274. ASSERT_POINTER(lpdwLen, DWORD);
  1275. ASSERT(AfxIsValidAddress(pstrName, *lpdwLen));
  1276. ASSERT(*lpdwLen != 0);
  1277. CString strTemp;
  1278. if (lpdwLen == NULL || !GetCurrentDirectoryAsURL(strTemp))
  1279. return FALSE;
  1280. if (pstrName == NULL)
  1281. *lpdwLen = strTemp.GetLength();
  1282. else
  1283. lstrcpyn(pstrName, (LPCTSTR) strTemp, max(0, *lpdwLen -1));
  1284. return TRUE;
  1285. }
  1286. BOOL CFtpConnection::GetCurrentDirectory(CString& strDirName) const
  1287. {
  1288. ASSERT_VALID(this);
  1289. ASSERT(m_hConnection != NULL);
  1290. DWORD dwLen = INTERNET_MAX_PATH_LENGTH;
  1291. LPTSTR pstrTarget = strDirName.GetBufferSetLength(dwLen);
  1292. BOOL bRet = FtpGetCurrentDirectory(m_hConnection, pstrTarget, &dwLen);
  1293. if (bRet)
  1294. strDirName.ReleaseBuffer(dwLen);
  1295. else
  1296. strDirName.ReleaseBuffer(0);
  1297. return bRet;
  1298. }
  1299. CInternetFile* CFtpConnection::OpenFile(LPCTSTR pstrFileName,
  1300. DWORD dwAccess /* = GENERIC_READ */,
  1301. DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */,
  1302. DWORD dwContext /* = 1 */)
  1303. {
  1304. ASSERT_VALID(this);
  1305. ASSERT(m_hConnection != NULL);
  1306. ASSERT(dwAccess != (GENERIC_READ | GENERIC_WRITE));
  1307. ASSERT(dwAccess == GENERIC_READ || dwAccess == GENERIC_WRITE);
  1308. ASSERT(AfxIsValidString(pstrFileName));
  1309. HINTERNET hFile;
  1310. if (dwContext == 1)
  1311. dwContext = m_dwContext;
  1312. hFile = FtpOpenFile(m_hConnection, pstrFileName, dwAccess,
  1313. dwFlags, dwContext);
  1314. if (hFile == NULL)
  1315. AfxThrowInternetException(dwContext);
  1316. CInternetFile* pFile = new CInternetFile(hFile, pstrFileName, this,
  1317. (dwAccess == GENERIC_READ));
  1318. return pFile;
  1319. }
  1320. BOOL CFtpConnection::PutFile(LPCTSTR pstrLocalFile, LPCTSTR pstrRemoteFile,
  1321. DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */,
  1322. DWORD dwContext /* = 1 */)
  1323. {
  1324. ASSERT_VALID(this);
  1325. ASSERT(m_hConnection != NULL);
  1326. ASSERT(AfxIsValidString(pstrRemoteFile));
  1327. ASSERT(AfxIsValidString(pstrLocalFile));
  1328. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1329. if (dwContext == 1)
  1330. dwContext = m_dwContext;
  1331. return FtpPutFile(m_hConnection, pstrLocalFile, pstrRemoteFile,
  1332. dwFlags, dwContext);
  1333. }
  1334. BOOL CFtpConnection::GetFile(LPCTSTR pstrRemoteFile, LPCTSTR pstrLocalFile,
  1335. BOOL bFailIfExists /* = TRUE */,
  1336. DWORD dwAttributes /* = FILE_ATTRIBUTE_NORMAL */,
  1337. DWORD dwFlags /* = FTP_TRANSFER_TYPE_BINARY */, DWORD dwContext /* = 1 */)
  1338. {
  1339. ASSERT_VALID(this);
  1340. ASSERT(m_hConnection != NULL);
  1341. ASSERT(AfxIsValidString(pstrRemoteFile));
  1342. ASSERT(AfxIsValidString(pstrLocalFile));
  1343. ASSERT(!(dwAttributes & FILE_ATTRIBUTE_DIRECTORY));
  1344. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1345. if (dwContext == 1)
  1346. dwContext = m_dwContext;
  1347. return FtpGetFile(m_hConnection, pstrRemoteFile, pstrLocalFile,
  1348. bFailIfExists, dwAttributes, dwFlags, dwContext);
  1349. }
  1350. #ifdef _DEBUG
  1351. void CFtpConnection::Dump(CDumpContext& dc) const
  1352. {
  1353. CInternetConnection::Dump(dc);
  1354. dc << "\nm_strServerName = " << m_strServerName;
  1355. }
  1356. void CFtpConnection::AssertValid() const
  1357. {
  1358. ASSERT(m_pSession != NULL);
  1359. if (m_hConnection != NULL)
  1360. {
  1361. ASSERT(AfxGetInternetHandleType(m_hConnection)
  1362. == INTERNET_HANDLE_TYPE_CONNECT_FTP);
  1363. }
  1364. }
  1365. #endif
  1366. /////////////////////////////////////////////////////////////////////////////
  1367. // CGopherConnection
  1368. CGopherConnection::~CGopherConnection()
  1369. {
  1370. }
  1371. CGopherConnection::CGopherConnection(CInternetSession* pSession,
  1372. LPCTSTR pstrServer, LPCTSTR pstrUserName /* = NULL */,
  1373. LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 0 */,
  1374. INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
  1375. : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1376. {
  1377. ASSERT(pSession != NULL);
  1378. ASSERT_KINDOF(CInternetSession, pSession);
  1379. ASSERT(AfxIsValidString(pstrServer));
  1380. m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1381. nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_GOPHER,
  1382. 0, m_dwContext);
  1383. if (m_hConnection == NULL)
  1384. AfxThrowInternetException(m_dwContext);
  1385. else
  1386. _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1387. }
  1388. CGopherConnection::CGopherConnection(CInternetSession* pSession,
  1389. HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext)
  1390. : CInternetConnection(pSession, pstrServer,
  1391. INTERNET_INVALID_PORT_NUMBER, dwContext)
  1392. {
  1393. ASSERT(pSession != NULL);
  1394. ASSERT(AfxIsValidString(pstrServer));
  1395. BOOL bBadType = FALSE;
  1396. if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_GOPHER)
  1397. {
  1398. ASSERT(FALSE); // used the wrong handle type
  1399. bBadType = TRUE;
  1400. }
  1401. m_hConnection = hConnected;
  1402. if (m_hConnection == NULL || bBadType)
  1403. AfxThrowInternetException(m_dwContext);
  1404. else
  1405. _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1406. }
  1407. CGopherLocator CGopherConnection::CreateLocator(LPCTSTR pstrLocator)
  1408. {
  1409. CGopherLocator ret(pstrLocator, lstrlen(pstrLocator));
  1410. return ret;
  1411. }
  1412. CGopherLocator CGopherConnection::CreateLocator(LPCTSTR pstrServerName,
  1413. LPCTSTR pstrDisplayString, LPCTSTR pstrSelectorString, DWORD dwGopherType,
  1414. INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */)
  1415. {
  1416. TCHAR szLocator[MAX_GOPHER_LOCATOR_LENGTH];
  1417. DWORD dwLocLen = MAX_GOPHER_LOCATOR_LENGTH;
  1418. ASSERT(AfxIsValidString(pstrDisplayString));
  1419. ASSERT(AfxIsValidString(pstrServerName));
  1420. ASSERT(AfxIsValidString(pstrSelectorString));
  1421. if (!GopherCreateLocator(pstrServerName, nPort,
  1422. pstrDisplayString, pstrSelectorString, dwGopherType,
  1423. szLocator, &dwLocLen))
  1424. AfxThrowInternetException(0);
  1425. CGopherLocator ret(szLocator, dwLocLen);
  1426. return ret;
  1427. }
  1428. CGopherLocator CGopherConnection::CreateLocator(
  1429. LPCTSTR pstrDisplayString, LPCTSTR pstrSelectorString, DWORD dwGopherType)
  1430. {
  1431. TCHAR szLocator[MAX_GOPHER_LOCATOR_LENGTH];
  1432. DWORD dwLocLen = MAX_GOPHER_LOCATOR_LENGTH;
  1433. ASSERT(AfxIsValidString(pstrDisplayString));
  1434. ASSERT(AfxIsValidString(pstrSelectorString));
  1435. if (!GopherCreateLocator(m_strServerName, m_nPort,
  1436. pstrDisplayString, pstrSelectorString, dwGopherType,
  1437. szLocator, &dwLocLen))
  1438. AfxThrowInternetException(m_dwContext);
  1439. CGopherLocator ret(szLocator, dwLocLen);
  1440. return ret;
  1441. }
  1442. BOOL CGopherConnection::GetAttribute(CGopherLocator& refLocator,
  1443. CString strRequestedAttributes, CString& strResult)
  1444. {
  1445. DWORD dwLen = 4*MIN_GOPHER_ATTRIBUTE_LENGTH; // more than the minimum
  1446. BOOL bRet;
  1447. LPTSTR pstrResult = strResult.GetBuffer(dwLen);
  1448. if (!GopherGetAttribute(m_hConnection, (LPCTSTR) refLocator,
  1449. pstrResult, NULL, dwLen, &dwLen,
  1450. NULL, m_dwContext))
  1451. {
  1452. bRet = FALSE;
  1453. strResult.ReleaseBuffer(0);
  1454. }
  1455. else
  1456. {
  1457. bRet = TRUE;
  1458. strResult.ReleaseBuffer(dwLen);
  1459. }
  1460. return bRet;
  1461. }
  1462. CGopherFile* CGopherConnection::OpenFile(CGopherLocator& refLocator,
  1463. DWORD dwFlags /* = 0 */, LPCTSTR pstrView /* = NULL */,
  1464. DWORD dwContext /* = 1 */)
  1465. {
  1466. ASSERT_VALID(this);
  1467. ASSERT(m_hConnection != NULL);
  1468. HINTERNET hFile;
  1469. if (dwContext == 1)
  1470. dwContext = m_dwContext;
  1471. hFile = GopherOpenFile(m_hConnection, (LPCTSTR) refLocator, pstrView,
  1472. dwFlags, dwContext);
  1473. if (hFile == NULL)
  1474. AfxThrowInternetException(dwContext);
  1475. CGopherFile* pFile = new CGopherFile(hFile, refLocator, this);
  1476. return pFile;
  1477. }
  1478. void CGopherConnection::Close()
  1479. {
  1480. CInternetConnection::Close();
  1481. }
  1482. #ifdef _DEBUG
  1483. void CGopherConnection::Dump(CDumpContext& dc) const
  1484. {
  1485. CInternetConnection::Dump(dc);
  1486. dc << "\nm_strServerName = " << m_strServerName;
  1487. }
  1488. void CGopherConnection::AssertValid() const
  1489. {
  1490. ASSERT(m_pSession != NULL);
  1491. if (m_hConnection != NULL)
  1492. {
  1493. ASSERT(AfxGetInternetHandleType(m_hConnection)
  1494. == INTERNET_HANDLE_TYPE_CONNECT_GOPHER);
  1495. }
  1496. }
  1497. #endif
  1498. /////////////////////////////////////////////////////////////////////////////
  1499. // CHttpConnection
  1500. CHttpConnection::~CHttpConnection()
  1501. {
  1502. }
  1503. CHttpConnection::CHttpConnection(CInternetSession* pSession,
  1504. HINTERNET hConnected, LPCTSTR pstrServer, DWORD dwContext /* = 0 */)
  1505. : CInternetConnection(pSession, pstrServer, INTERNET_INVALID_PORT_NUMBER, dwContext)
  1506. {
  1507. ASSERT(pSession != NULL);
  1508. ASSERT(AfxIsValidString(pstrServer));
  1509. BOOL bBadType = FALSE;
  1510. if (AfxGetInternetHandleType(hConnected) != INTERNET_HANDLE_TYPE_CONNECT_HTTP)
  1511. {
  1512. ASSERT(FALSE); // used the wrong handle type
  1513. bBadType = TRUE;
  1514. }
  1515. m_hConnection = hConnected;
  1516. if (m_hConnection == NULL || bBadType)
  1517. AfxThrowInternetException(m_dwContext, ERROR_INVALID_HANDLE);
  1518. else
  1519. _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1520. }
  1521. CHttpConnection::CHttpConnection(CInternetSession* pSession,
  1522. LPCTSTR pstrServer,
  1523. INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1524. LPCTSTR pstrUserName /* = NULL */,
  1525. LPCTSTR pstrPassword /* = NULL */, DWORD dwContext /* = 1 */)
  1526. : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1527. {
  1528. ASSERT(pSession != NULL);
  1529. ASSERT_KINDOF(CInternetSession, pSession);
  1530. ASSERT(AfxIsValidString(pstrServer));
  1531. m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1532. nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_HTTP,
  1533. 0, m_dwContext);
  1534. if (m_hConnection == NULL)
  1535. AfxThrowInternetException(m_dwContext);
  1536. else
  1537. _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1538. }
  1539. CHttpConnection::CHttpConnection(CInternetSession* pSession,
  1540. LPCTSTR pstrServer, DWORD dwFlags,
  1541. INTERNET_PORT nPort /* = INTERNET_INVALID_PORT_NUMBER */,
  1542. LPCTSTR pstrUserName /* = NULL */,
  1543. LPCTSTR pstrPassword /* = NULL */,
  1544. DWORD dwContext /* = 1 */)
  1545. : CInternetConnection(pSession, pstrServer, nPort, dwContext)
  1546. {
  1547. ASSERT(pSession != NULL);
  1548. ASSERT_KINDOF(CInternetSession, pSession);
  1549. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1550. ASSERT(AfxIsValidString(pstrServer));
  1551. m_hConnection = InternetConnect((HINTERNET) *pSession, pstrServer,
  1552. nPort, pstrUserName, pstrPassword, INTERNET_SERVICE_HTTP,
  1553. dwFlags, m_dwContext);
  1554. if (m_hConnection == NULL)
  1555. AfxThrowInternetException(m_dwContext);
  1556. else
  1557. _afxSessionMap.SetAt(m_hConnection, m_pSession);
  1558. }
  1559. void CHttpConnection::Close()
  1560. {
  1561. CInternetConnection::Close();
  1562. }
  1563. CHttpFile* CHttpConnection::OpenRequest(LPCTSTR pstrVerb,
  1564. LPCTSTR pstrObjectName, LPCTSTR pstrReferer, DWORD dwContext,
  1565. LPCTSTR* ppstrAcceptTypes, LPCTSTR pstrVersion, DWORD dwFlags)
  1566. {
  1567. ASSERT_VALID(this);
  1568. ASSERT(m_hConnection != NULL);
  1569. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1570. if (dwContext == 1)
  1571. dwContext = m_dwContext;
  1572. if (pstrVersion == NULL)
  1573. pstrVersion = HTTP_VERSION;
  1574. HINTERNET hFile;
  1575. hFile = HttpOpenRequest(m_hConnection, pstrVerb, pstrObjectName,
  1576. pstrVersion, pstrReferer, ppstrAcceptTypes, dwFlags, dwContext);
  1577. CHttpFile* pRet = new CHttpFile(hFile, pstrVerb, pstrObjectName, this);
  1578. pRet->m_dwContext = dwContext;
  1579. return pRet;
  1580. }
  1581. CHttpFile* CHttpConnection::OpenRequest(int nVerb,
  1582. LPCTSTR pstrObjectName, LPCTSTR pstrReferer /* = NULL */, DWORD dwContext,
  1583. LPCTSTR* ppstrAcceptTypes /* = NULL */,
  1584. LPCTSTR pstrVersion /* = NULL */, DWORD dwFlags)
  1585. {
  1586. ASSERT_VALID(this);
  1587. ASSERT(m_hConnection != NULL);
  1588. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1589. ASSERT(AfxIsValidString(pstrObjectName));
  1590. ASSERT(nVerb >= _HTTP_VERB_MIN && nVerb <= _HTTP_VERB_MAX);
  1591. LPCTSTR pstrVerb;
  1592. if (nVerb >= _HTTP_VERB_MIN && nVerb <= _HTTP_VERB_MAX)
  1593. pstrVerb = szHtmlVerbs[nVerb];
  1594. else
  1595. pstrVerb = _T("");
  1596. return OpenRequest(pstrVerb, pstrObjectName, pstrReferer,
  1597. dwContext, ppstrAcceptTypes, pstrVersion, dwFlags);
  1598. }
  1599. #ifdef _DEBUG
  1600. void CHttpConnection::Dump(CDumpContext& dc) const
  1601. {
  1602. CInternetConnection::Dump(dc);
  1603. dc << "\nm_strServerName = " << m_strServerName;
  1604. }
  1605. void CHttpConnection::AssertValid() const
  1606. {
  1607. ASSERT(m_pSession != NULL);
  1608. if (m_hConnection != NULL)
  1609. {
  1610. ASSERT(AfxGetInternetHandleType(m_hConnection)
  1611. == INTERNET_HANDLE_TYPE_CONNECT_HTTP);
  1612. }
  1613. }
  1614. #endif
  1615. /////////////////////////////////////////////////////////////////////////////
  1616. // CHttpFile
  1617. CHttpFile::CHttpFile(HINTERNET hFile, HINTERNET hSession, LPCTSTR pstrObject,
  1618. LPCTSTR pstrServer, LPCTSTR pstrVerb, DWORD dwContext)
  1619. : CInternetFile(hFile, hSession, pstrObject, pstrServer, dwContext, TRUE),
  1620. m_strVerb(pstrVerb), m_strObject(pstrObject)
  1621. {
  1622. // caller must set _afxSessionMap!
  1623. ASSERT(AfxIsValidString(pstrVerb));
  1624. }
  1625. CHttpFile::CHttpFile(HINTERNET hFile, LPCTSTR pstrVerb, LPCTSTR pstrObject,
  1626. CHttpConnection* pConnection)
  1627. : CInternetFile(hFile, pstrObject, pConnection, TRUE),
  1628. m_strVerb(pstrVerb), m_strObject(pstrObject)
  1629. {
  1630. ASSERT(pstrVerb != NULL);
  1631. ASSERT(pstrObject != NULL);
  1632. ASSERT(pConnection != NULL);
  1633. ASSERT_VALID(pConnection);
  1634. }
  1635. CHttpFile::~CHttpFile()
  1636. {
  1637. }
  1638. void CHttpFile::Close()
  1639. {
  1640. CInternetFile::Close();
  1641. }
  1642. DWORD CHttpFile::ErrorDlg(CWnd* pParent /* = NULL */,
  1643. DWORD dwError /* = ERROR_INTERNET_INCORRECT_PASSWORD */,
  1644. DWORD dwFlags /* = FLAGS_ERROR_UI_FLAGS_GENERATE_DATA | FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS*/,
  1645. LPVOID* lppvData /* = NULL */)
  1646. {
  1647. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1648. HWND hWnd;
  1649. LPVOID lpEmpty;
  1650. LPVOID* lppvHolder;
  1651. if (lppvData == NULL)
  1652. {
  1653. lpEmpty = NULL;
  1654. lppvHolder = &lpEmpty;
  1655. }
  1656. else
  1657. lppvHolder = lppvData;
  1658. if (pParent == NULL || pParent->m_hWnd == NULL)
  1659. hWnd = GetDesktopWindow();
  1660. else
  1661. hWnd = pParent->m_hWnd;
  1662. return InternetErrorDlg(hWnd, m_hFile, dwError, dwFlags, lppvHolder);
  1663. }
  1664. CString CHttpFile::GetVerb() const
  1665. {
  1666. ASSERT_VALID(this);
  1667. ASSERT(m_hFile != NULL);
  1668. return m_strVerb;
  1669. }
  1670. CString CHttpFile::GetObject() const
  1671. {
  1672. ASSERT_VALID(this);
  1673. ASSERT(m_hFile != NULL);
  1674. return m_strObject;
  1675. }
  1676. CString CHttpFile::GetFileURL() const
  1677. {
  1678. ASSERT_VALID(this);
  1679. ASSERT(m_hFile != NULL);
  1680. CString str(_afxURLhttp);
  1681. if (m_hConnection != NULL)
  1682. {
  1683. str += m_strServerName;
  1684. int nLen = m_strObject.GetLength();
  1685. if (nLen > 0)
  1686. {
  1687. if (m_strObject[0] != '/' && m_strObject[0] != '\\')
  1688. str += '/';
  1689. str += m_strObject;
  1690. }
  1691. }
  1692. return str;
  1693. }
  1694. BOOL CHttpFile::AddRequestHeaders(LPCTSTR pstrHeaders,
  1695. DWORD dwModifiers /* = HTTP_ADDREQ_FLAG_ADD */,
  1696. int dwHeadersLen /* = -1 */)
  1697. {
  1698. ASSERT(AfxIsValidString(pstrHeaders));
  1699. ASSERT(dwHeadersLen == 0 || pstrHeaders != NULL);
  1700. ASSERT_VALID(this);
  1701. ASSERT(m_hFile != NULL);
  1702. if (dwHeadersLen == -1)
  1703. if (pstrHeaders == NULL)
  1704. dwHeadersLen = 0;
  1705. else
  1706. dwHeadersLen = lstrlen(pstrHeaders);
  1707. return HttpAddRequestHeaders(m_hFile, pstrHeaders, dwHeadersLen,
  1708. dwModifiers);
  1709. }
  1710. BOOL CHttpFile::AddRequestHeaders(CString& str,
  1711. DWORD dwModifiers /* = HTTP_ADDREQ_FLAG_ADD */)
  1712. {
  1713. return AddRequestHeaders((LPCTSTR) str, dwModifiers, str.GetLength());
  1714. }
  1715. BOOL CHttpFile::SendRequest(LPCTSTR pstrHeaders /* = NULL */,
  1716. DWORD dwHeadersLen /* = 0 */, LPVOID lpOptional /* = NULL */,
  1717. DWORD dwOptionalLen /* = 0 */)
  1718. {
  1719. ASSERT(dwOptionalLen == 0 || lpOptional != NULL);
  1720. ASSERT(dwHeadersLen == 0 || pstrHeaders != NULL);
  1721. ASSERT_VALID(this);
  1722. ASSERT(m_hFile != NULL);
  1723. BOOL bRet = HttpSendRequest(m_hFile,
  1724. pstrHeaders, dwHeadersLen, lpOptional, dwOptionalLen);
  1725. if (!bRet)
  1726. AfxThrowInternetException(m_dwContext);
  1727. return bRet;
  1728. }
  1729. BOOL CHttpFile::EndRequest(
  1730. DWORD dwFlags /* = 0 */,
  1731. LPINTERNET_BUFFERS lpBuffIn /* = NULL */, DWORD dwContext /* = 1 */)
  1732. {
  1733. ASSERT(m_hFile != NULL);
  1734. ASSERT(m_bReadMode == -1);
  1735. if (dwContext == 1)
  1736. dwContext = m_dwContext;
  1737. BOOL bRet = HttpEndRequest(m_hFile, lpBuffIn, dwFlags, dwContext);
  1738. if (!bRet)
  1739. AfxThrowInternetException(m_dwContext);
  1740. return bRet;
  1741. }
  1742. BOOL CHttpFile::SendRequestEx(DWORD dwTotalLen,
  1743. DWORD dwFlags /* = HSR_INITIATE */, DWORD dwContext /* = 1 */)
  1744. {
  1745. ASSERT(m_hFile != NULL);
  1746. INTERNET_BUFFERS buffer;
  1747. memset(&buffer, 0, sizeof(buffer));
  1748. buffer.dwStructSize = sizeof(buffer);
  1749. buffer.dwBufferTotal = dwTotalLen;
  1750. if (dwContext == 1)
  1751. dwContext = m_dwContext;
  1752. return SendRequestEx(&buffer, NULL, dwFlags, dwContext);
  1753. }
  1754. BOOL CHttpFile::SendRequestEx(LPINTERNET_BUFFERS lpBuffIn,
  1755. LPINTERNET_BUFFERS lpBuffOut, DWORD dwFlags /* = HSR_INITIATE */,
  1756. DWORD dwContext /* = 1 */)
  1757. {
  1758. ASSERT(m_hFile != NULL);
  1759. ASSERT_NULL_OR_POINTER(lpBuffIn, INTERNET_BUFFERS);
  1760. ASSERT_NULL_OR_POINTER(lpBuffOut, INTERNET_BUFFERS);
  1761. if (dwContext == 1)
  1762. dwContext = m_dwContext;
  1763. BOOL bRet = HttpSendRequestEx(m_hFile, lpBuffIn, lpBuffOut,
  1764. dwFlags, dwContext);
  1765. if (!bRet)
  1766. AfxThrowInternetException(m_dwContext);
  1767. m_bReadMode = -1;
  1768. return bRet;
  1769. }
  1770. BOOL CHttpFile::SendRequest(CString& strHeaders,
  1771. LPVOID lpOptional /* = NULL */, DWORD dwOptionalLen /* = 0 */)
  1772. {
  1773. ASSERT(dwOptionalLen == 0 || lpOptional != NULL);
  1774. ASSERT_VALID(this);
  1775. ASSERT(m_hFile != NULL);
  1776. return SendRequest((LPCTSTR) strHeaders, strHeaders.GetLength(),
  1777. lpOptional, dwOptionalLen);
  1778. }
  1779. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel,
  1780. LPVOID lpvBuffer, LPDWORD lpdwBufferLength, LPDWORD lpdwIndex) const
  1781. {
  1782. ASSERT((HTTP_QUERY_HEADER_MASK & dwInfoLevel) <= HTTP_QUERY_MAX &&
  1783. dwInfoLevel != 0);
  1784. ASSERT(lpvBuffer != NULL && *lpdwBufferLength > 0);
  1785. ASSERT_VALID(this);
  1786. ASSERT(m_hFile != NULL);
  1787. return HttpQueryInfo(m_hFile, dwInfoLevel, lpvBuffer,
  1788. lpdwBufferLength, lpdwIndex);
  1789. }
  1790. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, DWORD& dwResult,
  1791. LPDWORD lpdwIndex /* = NULL */) const
  1792. {
  1793. dwInfoLevel |= HTTP_QUERY_FLAG_NUMBER;
  1794. DWORD dwDWSize = sizeof(DWORD);
  1795. return QueryInfo(dwInfoLevel, &dwResult, &dwDWSize, lpdwIndex);
  1796. }
  1797. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, SYSTEMTIME* pSystemTime,
  1798. LPDWORD lpdwIndex /* = NULL */) const
  1799. {
  1800. dwInfoLevel |= HTTP_QUERY_FLAG_SYSTEMTIME;
  1801. DWORD dwTimeSize = sizeof(SYSTEMTIME);
  1802. return QueryInfo(dwInfoLevel, pSystemTime, &dwTimeSize, lpdwIndex);
  1803. }
  1804. BOOL CHttpFile::QueryInfoStatusCode(DWORD& dwStatusCode) const
  1805. {
  1806. ASSERT_VALID(this);
  1807. ASSERT(m_hFile != NULL);
  1808. TCHAR szBuffer[80];
  1809. DWORD dwLen = _countof(szBuffer);
  1810. BOOL bRet;
  1811. bRet = HttpQueryInfo(m_hFile, HTTP_QUERY_STATUS_CODE,
  1812. szBuffer, &dwLen, NULL);
  1813. if (bRet)
  1814. dwStatusCode = (DWORD) _ttol(szBuffer);
  1815. return bRet;
  1816. }
  1817. BOOL CHttpFile::QueryInfo(DWORD dwInfoLevel, CString& str,
  1818. LPDWORD lpdwIndex) const
  1819. {
  1820. ASSERT(dwInfoLevel <= HTTP_QUERY_MAX && dwInfoLevel >= 0);
  1821. ASSERT_VALID(this);
  1822. ASSERT(m_hFile != NULL);
  1823. BOOL bRet;
  1824. DWORD dwLen = 0;
  1825. // ask for nothing to see how long the return really is
  1826. str.Empty();
  1827. if (HttpQueryInfo(m_hFile, dwInfoLevel, NULL, &dwLen, 0))
  1828. bRet = TRUE;
  1829. else
  1830. {
  1831. // now that we know how long it is, ask for exactly that much
  1832. // space and really request the header from the API
  1833. LPTSTR pstr = str.GetBufferSetLength(dwLen);
  1834. bRet = HttpQueryInfo(m_hFile, dwInfoLevel, pstr, &dwLen, lpdwIndex);
  1835. if (bRet)
  1836. str.ReleaseBuffer(dwLen);
  1837. else
  1838. str.ReleaseBuffer(0);
  1839. }
  1840. return bRet;
  1841. }
  1842. #ifdef _DEBUG
  1843. void CHttpFile::Dump(CDumpContext& dc) const
  1844. {
  1845. dc << "\nm_strFileName = " << m_strFileName;
  1846. dc << "\nm_strVerb = " << m_strVerb;
  1847. }
  1848. void CHttpFile::AssertValid() const
  1849. {
  1850. CInternetFile::AssertValid();
  1851. }
  1852. #endif
  1853. /////////////////////////////////////////////////////////////////////////////
  1854. // CGopherFile
  1855. CGopherFile::CGopherFile(HINTERNET hFile, CGopherLocator& refLocator,
  1856. CGopherConnection* pConnection)
  1857. : CInternetFile(hFile, _T(""), pConnection, TRUE),
  1858. m_Locator(refLocator)
  1859. {
  1860. ASSERT(pConnection != NULL);
  1861. ASSERT_VALID(pConnection);
  1862. }
  1863. CGopherFile::CGopherFile(HINTERNET hFile, HINTERNET hSession,
  1864. LPCTSTR pstrLocator, DWORD dwLocLen, DWORD dwContext)
  1865. : CInternetFile(hFile, hSession, _T(""), _T(""), dwContext, TRUE),
  1866. m_Locator(pstrLocator, dwLocLen)
  1867. {
  1868. // caller muset set _afxSessionMap!
  1869. }
  1870. CGopherFile::~CGopherFile()
  1871. {
  1872. }
  1873. void CGopherFile::Close()
  1874. {
  1875. CInternetFile::Close();
  1876. }
  1877. void CGopherFile::Write(const void* lpBuf, UINT nCount)
  1878. {
  1879. UNUSED_ALWAYS(lpBuf);
  1880. UNUSED_ALWAYS(nCount);
  1881. ASSERT(FALSE);
  1882. AfxThrowNotSupportedException();
  1883. }
  1884. void CGopherFile::WriteString(LPCTSTR pstr)
  1885. {
  1886. UNUSED_ALWAYS(pstr);
  1887. ASSERT(FALSE);
  1888. AfxThrowNotSupportedException();
  1889. }
  1890. #ifdef _DEBUG
  1891. void CGopherFile::Dump(CDumpContext& dc) const
  1892. {
  1893. CInternetFile::Dump(dc);
  1894. }
  1895. void CGopherFile::AssertValid() const
  1896. {
  1897. CInternetFile::AssertValid();
  1898. }
  1899. #endif
  1900. /////////////////////////////////////////////////////////////////////////////
  1901. // CFtpFileFind
  1902. CFtpFileFind::CFtpFileFind(CFtpConnection* pConnection, DWORD dwContext)
  1903. {
  1904. ASSERT(pConnection != NULL);
  1905. ASSERT_KINDOF(CFtpConnection, pConnection);
  1906. m_pConnection = pConnection;
  1907. if (dwContext == 1)
  1908. dwContext = pConnection->GetContext();
  1909. m_dwContext = dwContext;
  1910. m_chDirSeparator = '/';
  1911. }
  1912. CFtpFileFind::~CFtpFileFind()
  1913. {
  1914. }
  1915. BOOL CFtpFileFind::FindFile(LPCTSTR pstrName /* = NULL */,
  1916. DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
  1917. {
  1918. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  1919. ASSERT(m_pConnection != NULL);
  1920. ASSERT_VALID(m_pConnection);
  1921. if (m_pConnection == NULL)
  1922. return FALSE;
  1923. Close();
  1924. m_pNextInfo = new WIN32_FIND_DATA;
  1925. m_bGotLast = FALSE;
  1926. if (pstrName == NULL)
  1927. pstrName = _T("*");
  1928. lstrcpy(((LPWIN32_FIND_DATA) m_pNextInfo)->cFileName, pstrName);
  1929. m_hContext = FtpFindFirstFile((HINTERNET) *m_pConnection,
  1930. pstrName, (LPWIN32_FIND_DATA) m_pNextInfo, dwFlags, m_dwContext);
  1931. if (m_hContext == NULL)
  1932. {
  1933. Close();
  1934. return FALSE;
  1935. }
  1936. LPCTSTR pstrRoot = _tcspbrk(pstrName, _T("\\/"));
  1937. CString strCWD;
  1938. m_pConnection->GetCurrentDirectory(strCWD);
  1939. if (pstrRoot == NULL)
  1940. {
  1941. if (m_pConnection->SetCurrentDirectory(pstrName))
  1942. {
  1943. m_pConnection->GetCurrentDirectory(m_strRoot);
  1944. m_pConnection->SetCurrentDirectory(strCWD);
  1945. }
  1946. else
  1947. m_strRoot = strCWD;
  1948. }
  1949. else
  1950. {
  1951. // find the last forward or backward whack
  1952. int nLast;
  1953. LPCTSTR pstrOther = _tcsrchr(pstrName, '\\');
  1954. pstrRoot = _tcsrchr(pstrName, '/');
  1955. if (pstrRoot == NULL)
  1956. pstrRoot = pstrName;
  1957. if (pstrOther == NULL)
  1958. pstrOther = pstrName;
  1959. if (pstrRoot >= pstrOther)
  1960. nLast = pstrRoot - pstrName;
  1961. else
  1962. nLast = pstrOther - pstrName;
  1963. // from the start to the last whack is the root
  1964. if (nLast == 0)
  1965. nLast++;
  1966. m_strRoot = pstrName;
  1967. m_strRoot = m_strRoot.Left(nLast);
  1968. }
  1969. return TRUE;
  1970. }
  1971. BOOL CFtpFileFind::FindNextFile()
  1972. {
  1973. ASSERT(m_hContext != NULL);
  1974. if (m_hContext == NULL)
  1975. return FALSE;
  1976. if (m_pFoundInfo == NULL)
  1977. m_pFoundInfo = new WIN32_FIND_DATA;
  1978. ASSERT_VALID(this);
  1979. void* pTemp = m_pFoundInfo;
  1980. m_pFoundInfo = m_pNextInfo;
  1981. m_pNextInfo = pTemp;
  1982. return InternetFindNextFile(m_hContext, m_pNextInfo);
  1983. }
  1984. void CFtpFileFind::CloseContext()
  1985. {
  1986. if (m_hContext != NULL && m_hContext != INVALID_HANDLE_VALUE)
  1987. {
  1988. InternetCloseHandle(m_hContext);
  1989. m_hContext = NULL;
  1990. }
  1991. return;
  1992. }
  1993. CString CFtpFileFind::GetFileURL() const
  1994. {
  1995. ASSERT_VALID(this);
  1996. ASSERT(m_hContext != NULL);
  1997. CString str;
  1998. if (m_hContext != NULL)
  1999. {
  2000. str += _afxURLftp;
  2001. str += m_pConnection->GetServerName();
  2002. str += GetFilePath();
  2003. }
  2004. return str;
  2005. }
  2006. #ifdef _DEBUG
  2007. void CFtpFileFind::Dump(CDumpContext& dc) const
  2008. {
  2009. CFileFind::Dump(dc);
  2010. dc << "m_hContext = " << m_hContext;
  2011. }
  2012. void CFtpFileFind::AssertValid() const
  2013. {
  2014. CFileFind::AssertValid();
  2015. }
  2016. #endif
  2017. /////////////////////////////////////////////////////////////////////////////
  2018. // CGopherFileFind
  2019. CGopherFileFind::CGopherFileFind(CGopherConnection* pConnection,
  2020. DWORD dwContext)
  2021. {
  2022. ASSERT(pConnection != NULL);
  2023. ASSERT_KINDOF(CGopherConnection, pConnection);
  2024. m_pConnection = pConnection;
  2025. if (dwContext == 1)
  2026. dwContext = pConnection->GetContext();
  2027. m_dwContext = dwContext;
  2028. }
  2029. CGopherFileFind::~CGopherFileFind()
  2030. {
  2031. }
  2032. BOOL CGopherFileFind::FindFile(LPCTSTR pstrString,
  2033. DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
  2034. {
  2035. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2036. Close();
  2037. m_pNextInfo = new GOPHER_FIND_DATA;
  2038. m_bGotLast = FALSE;
  2039. m_hContext = GopherFindFirstFile((HINTERNET) *m_pConnection,
  2040. NULL, pstrString,
  2041. (GOPHER_FIND_DATA*) m_pNextInfo, dwFlags, m_dwContext);
  2042. if (m_hContext == NULL)
  2043. Close();
  2044. return (m_hContext != NULL);
  2045. }
  2046. BOOL CGopherFileFind::FindFile(CGopherLocator& refLocator,
  2047. LPCTSTR pstrString, DWORD dwFlags /* = INTERNET_FLAG_RELOAD */)
  2048. {
  2049. ASSERT((dwFlags & INTERNET_FLAG_ASYNC) == 0);
  2050. Close();
  2051. m_pNextInfo = new GOPHER_FIND_DATA;
  2052. m_pFoundInfo = new GOPHER_FIND_DATA;
  2053. m_bGotLast = FALSE;
  2054. m_hContext = GopherFindFirstFile((HINTERNET) *m_pConnection,
  2055. (LPCTSTR) refLocator, pstrString,
  2056. (GOPHER_FIND_DATA*) m_pNextInfo, dwFlags, m_dwContext);
  2057. if (m_hContext == NULL)
  2058. Close();
  2059. return (m_hContext != NULL);
  2060. }
  2061. BOOL CGopherFileFind::FindNextFile()
  2062. {
  2063. ASSERT(m_hContext != NULL);
  2064. if (m_hContext == NULL)
  2065. return FALSE;
  2066. if (m_pFoundInfo == NULL)
  2067. m_pFoundInfo = new GOPHER_FIND_DATA;
  2068. ASSERT_VALID(this);
  2069. void* pTemp = m_pFoundInfo;
  2070. m_pFoundInfo = m_pNextInfo;
  2071. m_pNextInfo = pTemp;
  2072. return InternetFindNextFile(m_hContext, m_pNextInfo);
  2073. }
  2074. void CGopherFileFind::CloseContext()
  2075. {
  2076. if (m_hContext != NULL && m_hContext != INVALID_HANDLE_VALUE)
  2077. {
  2078. InternetCloseHandle(m_hContext);
  2079. m_hContext = NULL;
  2080. }
  2081. return;
  2082. }
  2083. CString CGopherFileFind::GetFileName() const
  2084. {
  2085. AfxThrowNotSupportedException();
  2086. return CString();
  2087. }
  2088. CString CGopherFileFind::GetFilePath() const
  2089. {
  2090. AfxThrowNotSupportedException();
  2091. return CString();
  2092. }
  2093. CString CGopherFileFind::GetFileTitle() const
  2094. {
  2095. AfxThrowNotSupportedException();
  2096. return CString();
  2097. }
  2098. BOOL CGopherFileFind::IsDots() const
  2099. {
  2100. // gophers never have dots
  2101. return FALSE;
  2102. }
  2103. BOOL CGopherFileFind::GetLastWriteTime(FILETIME* pTimeStamp) const
  2104. {
  2105. ASSERT(m_hContext != NULL);
  2106. ASSERT_POINTER(pTimeStamp, FILETIME);
  2107. ASSERT_VALID(this);
  2108. if (m_pFoundInfo != NULL && pTimeStamp != NULL)
  2109. {
  2110. *pTimeStamp = ((LPGOPHER_FIND_DATA) m_pFoundInfo)->LastModificationTime;
  2111. return TRUE;
  2112. }
  2113. else
  2114. return FALSE;
  2115. }
  2116. BOOL CGopherFileFind::GetLastAccessTime(FILETIME* pTimeStamp) const
  2117. {
  2118. ASSERT_POINTER(pTimeStamp, FILETIME);
  2119. return GetLastWriteTime(pTimeStamp);
  2120. }
  2121. BOOL CGopherFileFind::GetCreationTime(FILETIME* pTimeStamp) const
  2122. {
  2123. ASSERT_POINTER(pTimeStamp, FILETIME);
  2124. return GetLastWriteTime(pTimeStamp);
  2125. }
  2126. BOOL CGopherFileFind::GetLastWriteTime(CTime& refTime) const
  2127. {
  2128. ASSERT(m_hContext != NULL);
  2129. ASSERT_VALID(this);
  2130. if (m_pFoundInfo != NULL)
  2131. {
  2132. refTime = CTime(((LPGOPHER_FIND_DATA) m_pFoundInfo)->LastModificationTime);
  2133. return TRUE;
  2134. }
  2135. else
  2136. return FALSE;
  2137. }
  2138. BOOL CGopherFileFind::GetCreationTime(CTime& refTime) const
  2139. {
  2140. return GetLastWriteTime(refTime);
  2141. }
  2142. BOOL CGopherFileFind::GetLastAccessTime(CTime& refTime) const
  2143. {
  2144. return GetLastWriteTime(refTime);
  2145. }
  2146. CString CGopherFileFind::GetFileURL() const
  2147. {
  2148. AfxThrowNotSupportedException();
  2149. return CString();
  2150. }
  2151. CString CGopherFileFind::GetRoot() const
  2152. {
  2153. AfxThrowNotSupportedException();
  2154. return CString();
  2155. }
  2156. CGopherLocator CGopherFileFind::GetLocator() const
  2157. {
  2158. ASSERT_VALID(this);
  2159. ASSERT(m_pConnection != NULL && m_hContext != NULL);
  2160. return m_pConnection->CreateLocator(
  2161. ((LPGOPHER_FIND_DATA) m_pFoundInfo)->Locator);
  2162. }
  2163. CString CGopherFileFind::GetScreenName() const
  2164. {
  2165. ASSERT_VALID(this);
  2166. ASSERT(m_hContext != NULL);
  2167. CString str;
  2168. if (m_pFoundInfo != NULL)
  2169. str = ((LPGOPHER_FIND_DATA) m_pFoundInfo)->DisplayString;
  2170. return str;
  2171. }
  2172. DWORD CGopherFileFind::GetLength() const
  2173. {
  2174. ASSERT_VALID(this);
  2175. if (m_pFoundInfo != NULL)
  2176. return ((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeLow;
  2177. else
  2178. return 0;
  2179. }
  2180. #if defined(_X86_) || defined(_ALPHA_)
  2181. __int64 CGopherFileFind::GetLength64() const
  2182. {
  2183. ASSERT_VALID(this);
  2184. if (m_pFoundInfo != NULL)
  2185. return ((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeLow +
  2186. (((LPGOPHER_FIND_DATA) m_pFoundInfo)->SizeHigh << 32);
  2187. else
  2188. return 0;
  2189. }
  2190. #endif
  2191. #ifdef _DEBUG
  2192. void CGopherFileFind::Dump(CDumpContext& dc) const
  2193. {
  2194. CFileFind::Dump(dc);
  2195. dc << "m_hContext = " << m_hContext;
  2196. }
  2197. void CGopherFileFind::AssertValid() const
  2198. {
  2199. CFileFind::AssertValid();
  2200. }
  2201. #endif
  2202. /////////////////////////////////////////////////////////////////////////////
  2203. // CGopherLocator
  2204. CGopherLocator::CGopherLocator(LPCTSTR pstrLocator, DWORD dwLocLen)
  2205. {
  2206. ASSERT(AfxIsValidString(pstrLocator));
  2207. LPTSTR pstr = m_Locator.GetBufferSetLength(dwLocLen);
  2208. memcpy(pstr, pstrLocator, dwLocLen);
  2209. m_Locator.ReleaseBuffer(dwLocLen);
  2210. m_dwBufferLength = dwLocLen;
  2211. }
  2212. CGopherLocator::~CGopherLocator()
  2213. {
  2214. }
  2215. /////////////////////////////////////////////////////////////////////////////
  2216. // exception handling
  2217. void AFXAPI AfxThrowInternetException(DWORD dwContext, DWORD dwError /* = 0 */)
  2218. {
  2219. if (dwError == 0)
  2220. dwError = ::GetLastError();
  2221. CInternetException* pException = new CInternetException(dwError);
  2222. pException->m_dwContext = dwContext;
  2223. TRACE1("Warning: throwing CInternetException for error %d\n", dwError);
  2224. THROW(pException);
  2225. }
  2226. BOOL CInternetException::GetErrorMessage(LPTSTR pstrError, UINT nMaxError,
  2227. PUINT pnHelpContext)
  2228. {
  2229. ASSERT(pstrError != NULL && AfxIsValidString(pstrError, nMaxError));
  2230. if (pnHelpContext != NULL)
  2231. *pnHelpContext = 0;
  2232. LPTSTR lpBuffer;
  2233. BOOL bRet = TRUE;
  2234. HINSTANCE hWinINetLibrary;
  2235. hWinINetLibrary = ::LoadLibraryA("WININET.DLL");
  2236. if (hWinINetLibrary == NULL ||
  2237. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE,
  2238. hWinINetLibrary, m_dwError,
  2239. MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  2240. (LPTSTR) &lpBuffer, 0, NULL) == 0)
  2241. {
  2242. // it failed! try Windows...
  2243. bRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  2244. NULL, m_dwError,
  2245. MAKELANGID(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),
  2246. (LPTSTR) &lpBuffer, 0, NULL);
  2247. }
  2248. if (!bRet)
  2249. *pstrError = '\0';
  2250. else
  2251. {
  2252. if (m_dwError == ERROR_INTERNET_EXTENDED_ERROR)
  2253. {
  2254. LPTSTR lpExtended;
  2255. DWORD dwLength = 0;
  2256. DWORD dwError;
  2257. // find the length of the error
  2258. if (!InternetGetLastResponseInfo(&dwError, NULL, &dwLength) &&
  2259. GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  2260. {
  2261. lpExtended = (LPTSTR) LocalAlloc(LPTR, dwLength);
  2262. InternetGetLastResponseInfo(&dwError, lpExtended, &dwLength);
  2263. lstrcpyn(pstrError, lpExtended, nMaxError);
  2264. pstrError += dwLength;
  2265. nMaxError -= dwLength;
  2266. if (nMaxError < 0)
  2267. nMaxError = 0;
  2268. LocalFree(lpExtended);
  2269. }
  2270. else
  2271. TRACE0("Warning: Extended error reported with no response info\n");
  2272. bRet = TRUE;
  2273. }
  2274. else
  2275. {
  2276. lstrcpyn(pstrError, lpBuffer, nMaxError);
  2277. bRet = TRUE;
  2278. }
  2279. LocalFree(lpBuffer);
  2280. }
  2281. #ifndef _AFXDLL
  2282. ::FreeLibrary(hWinINetLibrary);
  2283. #endif
  2284. return bRet;
  2285. }
  2286. CInternetException::CInternetException(DWORD dwError)
  2287. {
  2288. m_dwError = dwError;
  2289. }
  2290. CInternetException::~CInternetException()
  2291. {
  2292. }
  2293. #ifdef _DEBUG
  2294. void CInternetException::Dump(CDumpContext& dc) const
  2295. {
  2296. CObject::Dump(dc);
  2297. dc << "m_dwError = " << m_dwError;
  2298. dc << "\nm_dwContext = " << m_dwContext;
  2299. }
  2300. #endif
  2301. /////////////////////////////////////////////////////////////////////////////
  2302. // Inline function declarations expanded out-of-line
  2303. #ifndef _AFX_ENABLE_INLINES
  2304. // expand inlines for OLE dialog APIs
  2305. static char _szAfxInetInl[] = "afxinet.inl";
  2306. #undef THIS_FILE
  2307. #define THIS_FILE _szAfxInetInl
  2308. #define _AFXINET_INLINE
  2309. #include "afxinet.inl"
  2310. #endif //!_AFX_ENABLE_INLINES
  2311. /////////////////////////////////////////////////////////////////////////////
  2312. // Pre-startup code
  2313. #ifdef AFX_INIT_SEG
  2314. #pragma code_seg(AFX_INIT_SEG)
  2315. #endif
  2316. IMPLEMENT_DYNAMIC(CInternetException, CException)
  2317. IMPLEMENT_DYNAMIC(CInternetFile, CStdioFile)
  2318. IMPLEMENT_DYNAMIC(CHttpFile, CInternetFile)
  2319. IMPLEMENT_DYNAMIC(CGopherFile, CInternetFile)
  2320. IMPLEMENT_DYNAMIC(CInternetSession, CObject)
  2321. IMPLEMENT_DYNAMIC(CInternetConnection, CObject)
  2322. IMPLEMENT_DYNAMIC(CFtpConnection, CInternetConnection)
  2323. IMPLEMENT_DYNAMIC(CHttpConnection, CInternetConnection)
  2324. IMPLEMENT_DYNAMIC(CGopherConnection, CInternetConnection)
  2325. IMPLEMENT_DYNAMIC(CFtpFileFind, CFileFind)
  2326. IMPLEMENT_DYNAMIC(CGopherFileFind, CFileFind)
  2327. #pragma warning(disable: 4074)
  2328. #pragma init_seg(compiler)
  2329. CSessionMapPtrToPtr _afxSessionMap;