ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pop3transport.c
Go to the documentation of this file.
00001 /*
00002  * POP3 Transport
00003  *
00004  * Copyright 2008 Hans Leidekker for CodeWeavers
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00019  */
00020 
00021 #define COBJMACROS
00022 #define NONAMELESSUNION
00023 
00024 #include <stdarg.h>
00025 #include <stdio.h>
00026 
00027 #include "windef.h"
00028 #include "winbase.h"
00029 #include "winnt.h"
00030 #include "winuser.h"
00031 #include "objbase.h"
00032 #include "mimeole.h"
00033 #include "wine/debug.h"
00034 
00035 #include "inetcomm_private.h"
00036 
00037 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
00038 
00039 enum parse_state
00040 {
00041     STATE_NONE,
00042     STATE_OK,
00043     STATE_MULTILINE,
00044     STATE_DONE
00045 };
00046 
00047 typedef struct
00048 {
00049     InternetTransport InetTransport;
00050     ULONG refs;
00051     POP3COMMAND command;
00052     POP3CMDTYPE type;
00053     char *response;
00054     char *ptr;
00055     enum parse_state state;
00056     BOOL valid_info;
00057     DWORD msgid;
00058     DWORD preview_lines;
00059 } POP3Transport;
00060 
00061 static HRESULT parse_response(POP3Transport *This)
00062 {
00063     switch (This->state)
00064     {
00065     case STATE_NONE:
00066         if (strlen(This->response) < 3)
00067         {
00068             WARN("parse error\n");
00069             This->state = STATE_DONE;
00070             return S_FALSE;
00071         }
00072         if (!memcmp(This->response, "+OK", 3))
00073         {
00074             This->ptr = This->response + 3;
00075             This->state = STATE_OK;
00076             return S_OK;
00077         }
00078         This->state = STATE_DONE;
00079         return S_FALSE;
00080 
00081     default: return S_OK;
00082     }
00083 }
00084 
00085 static HRESULT parse_uidl_response(POP3Transport *This, POP3UIDL *uidl)
00086 {
00087     char *p;
00088 
00089     uidl->dwPopId = 0;
00090     uidl->pszUidl = NULL;
00091     switch (This->state)
00092     {
00093     case STATE_OK:
00094         if (This->type == POP3CMD_GET_POPID)
00095         {
00096             if ((p = strchr(This->ptr, ' ')))
00097             {
00098                 while (*p == ' ') p++;
00099                 sscanf(p, "%u", &uidl->dwPopId);
00100                 if ((p = strchr(p, ' ')))
00101                 {
00102                     while (*p == ' ') p++;
00103                     uidl->pszUidl = p;
00104                     This->valid_info = TRUE;
00105                 }
00106              }
00107              This->state = STATE_DONE;
00108              return S_OK;
00109         }
00110         This->state = STATE_MULTILINE;
00111         return S_OK;
00112 
00113     case STATE_MULTILINE:
00114         if (This->response[0] == '.' && !This->response[1])
00115         {
00116             This->valid_info = FALSE;
00117             This->state = STATE_DONE;
00118             return S_OK;
00119         }
00120         sscanf(This->response, "%u", &uidl->dwPopId);
00121         if ((p = strchr(This->response, ' ')))
00122         {
00123             while (*p == ' ') p++;
00124             uidl->pszUidl = p;
00125             This->valid_info = TRUE;
00126             return S_OK;
00127         }
00128 
00129     default:
00130         WARN("parse error\n");
00131         This->state = STATE_DONE;
00132         return S_FALSE;
00133     }
00134 }
00135 
00136 static HRESULT parse_stat_response(POP3Transport *This, POP3STAT *stat)
00137 {
00138     char *p;
00139 
00140     stat->cMessages = 0;
00141     stat->cbMessages = 0;
00142     switch (This->state)
00143     {
00144     case STATE_OK:
00145         if ((p = strchr(This->ptr, ' ')))
00146         {
00147             while (*p == ' ') p++;
00148             sscanf(p, "%u %u", &stat->cMessages, &stat->cbMessages);
00149             This->valid_info = TRUE;
00150             This->state = STATE_DONE;
00151             return S_OK;
00152         }
00153 
00154     default:
00155         WARN("parse error\n");
00156         This->state = STATE_DONE;
00157         return S_FALSE;
00158     }
00159 }
00160 
00161 static HRESULT parse_list_response(POP3Transport *This, POP3LIST *list)
00162 {
00163     char *p;
00164 
00165     list->dwPopId = 0;
00166     list->cbSize = 0;
00167     switch (This->state)
00168     {
00169     case STATE_OK:
00170         if (This->type == POP3CMD_GET_POPID)
00171         {
00172             if ((p = strchr(This->ptr, ' ')))
00173             {
00174                 while (*p == ' ') p++;
00175                 sscanf(p, "%u %u", &list->dwPopId, &list->cbSize);
00176                 This->valid_info = TRUE;
00177             }
00178             This->state = STATE_DONE;
00179             return S_OK;
00180         }
00181         This->state = STATE_MULTILINE;
00182         return S_OK;
00183 
00184     case STATE_MULTILINE:
00185         if (This->response[0] == '.' && !This->response[1])
00186         {
00187             This->valid_info = FALSE;
00188             This->state = STATE_DONE;
00189             return S_OK;
00190         }
00191         sscanf(This->response, "%u", &list->dwPopId);
00192         if ((p = strchr(This->response, ' ')))
00193         {
00194             while (*p == ' ') p++;
00195             sscanf(p, "%u", &list->cbSize);
00196             This->valid_info = TRUE;
00197             return S_OK;
00198         }
00199 
00200     default:
00201         WARN("parse error\n");
00202         This->state = STATE_DONE;
00203         return S_FALSE;
00204     }
00205 }
00206 
00207 static HRESULT parse_dele_response(POP3Transport *This, DWORD *dwPopId)
00208 {
00209     switch (This->state)
00210     {
00211     case STATE_OK:
00212         *dwPopId = 0; /* FIXME */
00213         This->state = STATE_DONE;
00214         return S_OK;
00215 
00216     default:
00217         WARN("parse error\n");
00218         This->state = STATE_DONE;
00219         return S_FALSE;
00220     }
00221 }
00222 
00223 static HRESULT parse_retr_response(POP3Transport *This, POP3RETR *retr)
00224 {
00225     switch (This->state)
00226     {
00227     case STATE_OK:
00228         retr->fHeader = FALSE;
00229         retr->fBody = FALSE;
00230         retr->dwPopId = This->msgid;
00231         retr->cbSoFar = 0;
00232         retr->pszLines = This->response;
00233         retr->cbLines = 0;
00234 
00235         This->state = STATE_MULTILINE;
00236         This->valid_info = FALSE;
00237         return S_OK;
00238 
00239     case STATE_MULTILINE:
00240     {
00241         int len;
00242 
00243         if (This->response[0] == '.' && !This->response[1])
00244         {
00245             retr->cbLines = retr->cbSoFar;
00246             This->state = STATE_DONE;
00247             return S_OK;
00248         }
00249         retr->fHeader = TRUE;
00250         if (!This->response[0]) retr->fBody = TRUE;
00251 
00252         len = strlen(This->response);
00253         retr->cbSoFar += len;
00254         retr->pszLines = This->response;
00255         retr->cbLines = len;
00256 
00257         This->valid_info = TRUE;
00258         return S_OK;
00259     }
00260 
00261     default:
00262         WARN("parse error\n");
00263         This->state = STATE_DONE;
00264         return S_FALSE;
00265     }
00266 }
00267 
00268 static HRESULT parse_top_response(POP3Transport *This, POP3TOP *top)
00269 {
00270     switch (This->state)
00271     {
00272     case STATE_OK:
00273         top->fHeader = FALSE;
00274         top->fBody = FALSE;
00275         top->dwPopId = This->msgid;
00276         top->cPreviewLines = This->preview_lines;
00277         top->cbSoFar = 0;
00278         top->pszLines = This->response;
00279         top->cbLines = 0;
00280 
00281         This->state = STATE_MULTILINE;
00282         This->valid_info = FALSE;
00283         return S_OK;
00284 
00285     case STATE_MULTILINE:
00286     {
00287         int len;
00288 
00289         if (This->response[0] == '.' && !This->response[1])
00290         {
00291             top->cbLines = top->cbSoFar;
00292             This->state = STATE_DONE;
00293             return S_OK;
00294         }
00295         top->fHeader = TRUE;
00296         if (!This->response[0]) top->fBody = TRUE;
00297 
00298         len = strlen(This->response);
00299         top->cbSoFar += len;
00300         top->pszLines = This->response;
00301         top->cbLines = len;
00302 
00303         This->valid_info = TRUE;
00304         return S_OK;
00305     }
00306 
00307     default:
00308         WARN("parse error\n");
00309         This->state = STATE_DONE;
00310         return S_FALSE;
00311     }
00312 }
00313 
00314 static void init_parser(POP3Transport *This, POP3COMMAND command, POP3CMDTYPE type)
00315 {
00316     This->state = STATE_NONE;
00317     This->command = command;
00318     This->type = type;
00319 }
00320 
00321 static HRESULT POP3Transport_ParseResponse(POP3Transport *This, char *pszResponse, POP3RESPONSE *pResponse)
00322 {
00323     HRESULT hr;
00324 
00325     TRACE("response: %s\n", debugstr_a(pszResponse));
00326 
00327     This->response = pszResponse;
00328     This->valid_info = FALSE;
00329     TRACE("state %u\n", This->state);
00330 
00331     if (SUCCEEDED((hr = parse_response(This))))
00332     {
00333         switch (This->command)
00334         {
00335         case POP3_UIDL: hr = parse_uidl_response(This, &pResponse->u.rUidlInfo); break;
00336         case POP3_STAT: hr = parse_stat_response(This, &pResponse->u.rStatInfo); break;
00337         case POP3_LIST: hr = parse_list_response(This, &pResponse->u.rListInfo); break;
00338         case POP3_DELE: hr = parse_dele_response(This, &pResponse->u.dwPopId); break;
00339         case POP3_RETR: hr = parse_retr_response(This, &pResponse->u.rRetrInfo); break;
00340         case POP3_TOP: hr = parse_top_response(This, &pResponse->u.rTopInfo); break;
00341         default:
00342             This->state = STATE_DONE;
00343             break;
00344         }
00345     }
00346     pResponse->command = This->command;
00347     pResponse->fDone = (This->state == STATE_DONE);
00348     pResponse->fValidInfo = This->valid_info;
00349     pResponse->rIxpResult.hrResult = hr;
00350     pResponse->rIxpResult.pszResponse = pszResponse;
00351     pResponse->rIxpResult.uiServerError = 0;
00352     pResponse->rIxpResult.hrServerError = pResponse->rIxpResult.hrResult;
00353     pResponse->rIxpResult.dwSocketError = WSAGetLastError();
00354     pResponse->rIxpResult.pszProblem = NULL;
00355     pResponse->pTransport = (IPOP3Transport *)&This->InetTransport.u.vtblPOP3;
00356 
00357     if (This->InetTransport.pCallback && This->InetTransport.fCommandLogging)
00358     {
00359         ITransportCallback_OnCommand(This->InetTransport.pCallback, CMD_RESP,
00360             pResponse->rIxpResult.pszResponse, pResponse->rIxpResult.hrServerError,
00361             (IInternetTransport *)&This->InetTransport.u.vtbl);
00362     }
00363     return S_OK;
00364 }
00365 
00366 static void POP3Transport_CallbackProcessDELEResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00367 {
00368     POP3Transport *This = (POP3Transport *)iface;
00369     POP3RESPONSE response;
00370     HRESULT hr;
00371 
00372     TRACE("\n");
00373 
00374     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00375     if (FAILED(hr))
00376     {
00377         /* FIXME: handle error */
00378         return;
00379     }
00380 
00381     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00382 }
00383 
00384 static void POP3Transport_CallbackRecvDELEResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00385 {
00386     POP3Transport *This = (POP3Transport *)iface;
00387 
00388     TRACE("\n");
00389     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessDELEResp);
00390 }
00391 
00392 static void POP3Transport_CallbackProcessNOOPResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00393 {
00394     POP3Transport *This = (POP3Transport *)iface;
00395     POP3RESPONSE response;
00396     HRESULT hr;
00397 
00398     TRACE("\n");
00399 
00400     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00401     if (FAILED(hr))
00402     {
00403         /* FIXME: handle error */
00404         return;
00405     }
00406 
00407     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00408 }
00409 
00410 static void POP3Transport_CallbackRecvNOOPResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00411 {
00412     POP3Transport *This = (POP3Transport *)iface;
00413 
00414     TRACE("\n");
00415     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessNOOPResp);
00416 }
00417 
00418 static void POP3Transport_CallbackProcessRSETResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00419 {
00420     POP3Transport *This = (POP3Transport *)iface;
00421     POP3RESPONSE response;
00422     HRESULT hr;
00423 
00424     TRACE("\n");
00425 
00426     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00427     if (FAILED(hr))
00428     {
00429         /* FIXME: handle error */
00430         return;
00431     }
00432 
00433     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00434 }
00435 
00436 static void POP3Transport_CallbackRecvRSETResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00437 {
00438     POP3Transport *This = (POP3Transport *)iface;
00439 
00440     TRACE("\n");
00441     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessRSETResp);
00442 }
00443 
00444 static void POP3Transport_CallbackProcessRETRResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00445 {
00446     POP3Transport *This = (POP3Transport *)iface;
00447     POP3RESPONSE response;
00448     HRESULT hr;
00449 
00450     TRACE("\n");
00451 
00452     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00453     if (FAILED(hr))
00454     {
00455         /* FIXME: handle error */
00456         return;
00457     }
00458 
00459     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00460 
00461     if (!response.fDone)
00462     {
00463         InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessRETRResp);
00464         return;
00465     }
00466 
00467     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00468 }
00469 
00470 static void POP3Transport_CallbackRecvRETRResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00471 {
00472     POP3Transport *This = (POP3Transport *)iface;
00473 
00474     TRACE("\n");
00475     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessRETRResp);
00476 }
00477 
00478 static void POP3Transport_CallbackProcessTOPResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00479 {
00480     POP3Transport *This = (POP3Transport *)iface;
00481     POP3RESPONSE response;
00482     HRESULT hr;
00483 
00484     TRACE("\n");
00485 
00486     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00487     if (FAILED(hr))
00488     {
00489         /* FIXME: handle error */
00490         return;
00491     }
00492 
00493     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00494 
00495     if (!response.fDone)
00496     {
00497         InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessTOPResp);
00498         return;
00499     }
00500 
00501     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00502 }
00503 
00504 static void POP3Transport_CallbackRecvTOPResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00505 {
00506     POP3Transport *This = (POP3Transport *)iface;
00507 
00508     TRACE("\n");
00509     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessTOPResp);
00510 }
00511 
00512 static void POP3Transport_CallbackProcessLISTResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00513 {
00514     POP3Transport *This = (POP3Transport *)iface;
00515     POP3RESPONSE response;
00516     HRESULT hr;
00517 
00518     TRACE("\n");
00519 
00520     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00521     if (FAILED(hr))
00522     {
00523         /* FIXME: handle error */
00524         return;
00525     }
00526 
00527     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00528 
00529     if (!response.fDone)
00530     {
00531         InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessLISTResp);
00532         return;
00533     }
00534 
00535     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00536 }
00537 
00538 static void POP3Transport_CallbackRecvLISTResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00539 {
00540     POP3Transport *This = (POP3Transport *)iface;
00541 
00542     TRACE("\n");
00543     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessLISTResp);
00544 }
00545 
00546 static void POP3Transport_CallbackProcessUIDLResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00547 {
00548     POP3Transport *This = (POP3Transport *)iface;
00549     POP3RESPONSE response;
00550     HRESULT hr;
00551 
00552     TRACE("\n");
00553 
00554     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00555     if (FAILED(hr))
00556     {
00557         /* FIXME: handle error */
00558         return;
00559     }
00560 
00561     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00562 
00563     if (!response.fDone)
00564     {
00565         InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessUIDLResp);
00566         return;
00567     }
00568 
00569     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00570 }
00571 
00572 static void POP3Transport_CallbackRecvUIDLResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00573 {
00574     POP3Transport *This = (POP3Transport *)iface;
00575 
00576     TRACE("\n");
00577     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessUIDLResp);
00578 }
00579 
00580 static void POP3Transport_CallbackProcessSTATResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00581 {
00582     POP3Transport *This = (POP3Transport *)iface;
00583     POP3RESPONSE response;
00584     HRESULT hr;
00585 
00586     TRACE("\n");
00587 
00588     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00589     if (FAILED(hr))
00590     {
00591         /* FIXME: handle error */
00592         return;
00593     }
00594 
00595     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00596 }
00597 
00598 static void POP3Transport_CallbackRecvSTATResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00599 {
00600     POP3Transport *This = (POP3Transport *)iface;
00601 
00602     TRACE("\n");
00603     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessSTATResp);
00604 }
00605 
00606 static void POP3Transport_CallbackProcessPASSResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00607 {
00608     POP3Transport *This = (POP3Transport *)iface;
00609     POP3RESPONSE response;
00610     HRESULT hr;
00611 
00612     TRACE("\n");
00613 
00614     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00615     if (FAILED(hr))
00616     {
00617         /* FIXME: handle error */
00618         return;
00619     }
00620 
00621     InternetTransport_ChangeStatus(&This->InetTransport, IXP_AUTHORIZED);
00622     InternetTransport_ChangeStatus(&This->InetTransport, IXP_CONNECTED);
00623 
00624     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00625 }
00626 
00627 static void POP3Transport_CallbackRecvPASSResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00628 {
00629     POP3Transport *This = (POP3Transport *)iface;
00630 
00631     TRACE("\n");
00632     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessPASSResp);
00633 }
00634 
00635 static void POP3Transport_CallbackProcessUSERResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00636 {
00637     static char pass[] = "PASS ";
00638     POP3Transport *This = (POP3Transport *)iface;
00639     POP3RESPONSE response;
00640     char *command;
00641     int len;
00642     HRESULT hr;
00643 
00644     TRACE("\n");
00645 
00646     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00647     if (FAILED(hr))
00648     {
00649         /* FIXME: handle error */
00650         return;
00651     }
00652 
00653     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00654 
00655     len = sizeof(pass) + strlen(This->InetTransport.ServerInfo.szPassword) + 2; /* "\r\n" */
00656     command = HeapAlloc(GetProcessHeap(), 0, len);
00657 
00658     strcpy(command, pass);
00659     strcat(command, This->InetTransport.ServerInfo.szPassword);
00660     strcat(command, "\r\n");
00661 
00662     init_parser(This, POP3_PASS, POP3_NONE);
00663 
00664     InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvPASSResp);
00665     HeapFree(GetProcessHeap(), 0, command);
00666 }
00667 
00668 static void POP3Transport_CallbackRecvUSERResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00669 {
00670     POP3Transport *This = (POP3Transport *)iface;
00671 
00672     TRACE("\n");
00673     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessUSERResp);
00674 }
00675 
00676 static void POP3Transport_CallbackSendUSERCmd(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00677 {
00678     static char user[] = "USER ";
00679     POP3Transport *This = (POP3Transport *)iface;
00680     char *command;
00681     int len;
00682 
00683     TRACE("\n");
00684 
00685     len = sizeof(user) + strlen(This->InetTransport.ServerInfo.szUserName) + 2; /* "\r\n" */
00686     command = HeapAlloc(GetProcessHeap(), 0, len);
00687 
00688     strcpy(command, user);
00689     strcat(command, This->InetTransport.ServerInfo.szUserName);
00690     strcat(command, "\r\n");
00691     InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvUSERResp);
00692 
00693     HeapFree(GetProcessHeap(), 0, command);
00694 }
00695 
00696 static void POP3Transport_CallbackProcessQUITResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00697 {
00698     POP3Transport *This = (POP3Transport *)iface;
00699     POP3RESPONSE response;
00700     HRESULT hr;
00701 
00702     TRACE("%s\n", debugstr_an(pBuffer, cbBuffer));
00703 
00704     hr = POP3Transport_ParseResponse(This, pBuffer, &response);
00705     if (FAILED(hr))
00706     {
00707         /* FIXME: handle error */
00708         return;
00709     }
00710 
00711     IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
00712     InternetTransport_DropConnection(&This->InetTransport);
00713 }
00714 
00715 static void POP3Transport_CallbackRecvQUITResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
00716 {
00717     POP3Transport *This = (POP3Transport *)iface;
00718 
00719     TRACE("\n");
00720     InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessQUITResponse);
00721 }
00722 
00723 static HRESULT WINAPI POP3Transport_QueryInterface(IPOP3Transport *iface, REFIID riid, void **ppv)
00724 {
00725     TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
00726 
00727     if (IsEqualIID(riid, &IID_IUnknown) ||
00728         IsEqualIID(riid, &IID_IInternetTransport) ||
00729         IsEqualIID(riid, &IID_IPOP3Transport))
00730     {
00731         *ppv = iface;
00732         IUnknown_AddRef(iface);
00733         return S_OK;
00734     }
00735     *ppv = NULL;
00736     FIXME("no interface for %s\n", debugstr_guid(riid));
00737     return E_NOINTERFACE;
00738 }
00739 
00740 static ULONG WINAPI POP3Transport_AddRef(IPOP3Transport *iface)
00741 {
00742     POP3Transport *This = (POP3Transport *)iface;
00743     return InterlockedIncrement((LONG *)&This->refs);
00744 }
00745 
00746 static ULONG WINAPI POP3Transport_Release(IPOP3Transport *iface)
00747 {
00748     POP3Transport *This = (POP3Transport *)iface;
00749     ULONG refs = InterlockedDecrement((LONG *)&This->refs);
00750     if (!refs)
00751     {
00752         TRACE("destroying %p\n", This);
00753         if (This->InetTransport.Status != IXP_DISCONNECTED)
00754             InternetTransport_DropConnection(&This->InetTransport);
00755         if (This->InetTransport.pCallback) ITransportCallback_Release(This->InetTransport.pCallback);
00756         HeapFree(GetProcessHeap(), 0, This);
00757     }
00758     return refs;
00759 }
00760 
00761 static HRESULT WINAPI POP3Transport_GetServerInfo(IPOP3Transport *iface,
00762     LPINETSERVER pInetServer)
00763 {
00764     POP3Transport *This = (POP3Transport *)iface;
00765 
00766     TRACE("(%p)\n", pInetServer);
00767     return InternetTransport_GetServerInfo(&This->InetTransport, pInetServer);
00768 }
00769 
00770 static IXPTYPE WINAPI POP3Transport_GetIXPType(IPOP3Transport *iface)
00771 {
00772     TRACE("()\n");
00773     return IXP_POP3;
00774 }
00775 
00776 static HRESULT WINAPI POP3Transport_IsState(IPOP3Transport *iface, IXPISSTATE isstate)
00777 {
00778     FIXME("(%u)\n", isstate);
00779     return E_NOTIMPL;
00780 }
00781 
00782 static HRESULT WINAPI POP3Transport_InetServerFromAccount(
00783     IPOP3Transport *iface, IImnAccount *pAccount, LPINETSERVER pInetServer)
00784 {
00785     POP3Transport *This = (POP3Transport *)iface;
00786 
00787     TRACE("(%p, %p)\n", pAccount, pInetServer);
00788     return InternetTransport_InetServerFromAccount(&This->InetTransport, pAccount, pInetServer);
00789 }
00790 
00791 static HRESULT WINAPI POP3Transport_Connect(IPOP3Transport *iface,
00792     LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging)
00793 {
00794     POP3Transport *This = (POP3Transport *)iface;
00795     HRESULT hr;
00796 
00797     TRACE("(%p, %s, %s)\n", pInetServer, fAuthenticate ? "TRUE" : "FALSE", fCommandLogging ? "TRUE" : "FALSE");
00798 
00799     hr = InternetTransport_Connect(&This->InetTransport, pInetServer, fAuthenticate, fCommandLogging);
00800     if (FAILED(hr))
00801         return hr;
00802 
00803     init_parser(This, POP3_USER, POP3_NONE);
00804     return InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackSendUSERCmd);
00805 }
00806 
00807 static HRESULT WINAPI POP3Transport_HandsOffCallback(IPOP3Transport *iface)
00808 {
00809     POP3Transport *This = (POP3Transport *)iface;
00810 
00811     TRACE("()\n");
00812     return InternetTransport_HandsOffCallback(&This->InetTransport);
00813 }
00814 
00815 static HRESULT WINAPI POP3Transport_Disconnect(IPOP3Transport *iface)
00816 {
00817     TRACE("()\n");
00818     return IPOP3Transport_CommandQUIT(iface);
00819 }
00820 
00821 static HRESULT WINAPI POP3Transport_DropConnection(IPOP3Transport *iface)
00822 {
00823     POP3Transport *This = (POP3Transport *)iface;
00824 
00825     TRACE("()\n");
00826     return InternetTransport_DropConnection(&This->InetTransport);
00827 }
00828 
00829 static HRESULT WINAPI POP3Transport_GetStatus(IPOP3Transport *iface,
00830     IXPSTATUS *pCurrentStatus)
00831 {
00832     POP3Transport *This = (POP3Transport *)iface;
00833 
00834     TRACE("()\n");
00835     return InternetTransport_GetStatus(&This->InetTransport, pCurrentStatus);
00836 }
00837 
00838 static HRESULT WINAPI POP3Transport_InitNew(IPOP3Transport *iface,
00839     LPSTR pszLogFilePath, IPOP3Callback *pCallback)
00840 {
00841     POP3Transport *This = (POP3Transport *)iface;
00842 
00843     TRACE("(%s, %p)\n", debugstr_a(pszLogFilePath), pCallback);
00844 
00845     if (!pCallback)
00846         return E_INVALIDARG;
00847 
00848     if (pszLogFilePath)
00849         FIXME("not using log file of %s, use Wine debug logging instead\n",
00850             debugstr_a(pszLogFilePath));
00851 
00852     IPOP3Callback_AddRef(pCallback);
00853     This->InetTransport.pCallback = (ITransportCallback *)pCallback;
00854     This->InetTransport.fInitialised = TRUE;
00855 
00856     return S_OK;
00857 }
00858 
00859 static HRESULT WINAPI POP3Transport_MarkItem(IPOP3Transport *iface, POP3MARKTYPE marktype,
00860     DWORD dwPopId, boolean fMarked)
00861 {
00862     FIXME("(%u, %u, %d)\n", marktype, dwPopId, fMarked);
00863     return E_NOTIMPL;
00864 }
00865 
00866 static HRESULT WINAPI POP3Transport_CommandAUTH(IPOP3Transport *iface, LPSTR pszAuthType)
00867 {
00868     FIXME("(%s)\n", pszAuthType);
00869     return E_NOTIMPL;
00870 }
00871 
00872 static HRESULT WINAPI POP3Transport_CommandUSER(IPOP3Transport *iface, LPSTR username)
00873 {
00874     static char user[] = "USER ";
00875     POP3Transport *This = (POP3Transport *)iface;
00876     char *command;
00877     int len;
00878 
00879     TRACE("(%s)\n", username);
00880 
00881     len = sizeof(user) + strlen(username) + 2; /* "\r\n" */
00882     if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
00883 
00884     strcpy(command, user);
00885     strcat(command, username);
00886     strcat(command, "\r\n");
00887 
00888     init_parser(This, POP3_USER, POP3_NONE);
00889     InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvUSERResp);
00890 
00891     HeapFree(GetProcessHeap(), 0, command);
00892     return S_OK;
00893 }
00894 
00895 static HRESULT WINAPI POP3Transport_CommandPASS(IPOP3Transport *iface, LPSTR password)
00896 {
00897     static char pass[] = "PASS ";
00898     POP3Transport *This = (POP3Transport *)iface;
00899     char *command;
00900     int len;
00901 
00902     TRACE("(%p)\n", password);
00903 
00904     len = sizeof(pass) + strlen(password) + 2; /* "\r\n" */
00905     if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
00906 
00907     strcpy(command, pass);
00908     strcat(command, password);
00909     strcat(command, "\r\n");
00910 
00911     init_parser(This, POP3_PASS, POP3_NONE);
00912     InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvPASSResp);
00913 
00914     HeapFree(GetProcessHeap(), 0, command);
00915     return S_OK;
00916 }
00917 
00918 static HRESULT WINAPI POP3Transport_CommandLIST(
00919     IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId)
00920 {
00921     static char list[] = "LIST %u\r\n";
00922     static char list_all[] = "LIST\r\n";
00923     POP3Transport *This = (POP3Transport *)iface;
00924     char *command;
00925     int len;
00926 
00927     TRACE("(%u, %u)\n", cmdtype, dwPopId);
00928 
00929     if (dwPopId)
00930     {
00931         len = sizeof(list) + 10 + 2; /* "4294967296" + "\r\n" */
00932         if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
00933         sprintf(command, list, dwPopId);
00934     }
00935     else command = list_all;
00936 
00937     init_parser(This, POP3_LIST, cmdtype);
00938     InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvLISTResp);
00939 
00940     if (dwPopId) HeapFree(GetProcessHeap(), 0, command);
00941     return S_OK;
00942 }
00943 
00944 static HRESULT WINAPI POP3Transport_CommandTOP(
00945     IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId, DWORD cPreviewLines)
00946 {
00947     static char top[] = "TOP %u %u\r\n";
00948     POP3Transport *This = (POP3Transport *)iface;
00949     char *command;
00950     int len;
00951 
00952     TRACE("(%u, %u, %u)\n", cmdtype, dwPopId, cPreviewLines);
00953 
00954     len = sizeof(top) + 20 + 2; /* 2 * "4294967296" + "\r\n" */
00955     if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
00956     sprintf(command, top, dwPopId, cPreviewLines);
00957 
00958     This->preview_lines = cPreviewLines;
00959     init_parser(This, POP3_TOP, cmdtype);
00960     InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvTOPResp);
00961 
00962     HeapFree(GetProcessHeap(), 0, command);
00963     return S_OK;
00964 }
00965 
00966 static HRESULT WINAPI POP3Transport_CommandQUIT(IPOP3Transport *iface)
00967 {
00968     static char command[] = "QUIT\r\n";
00969     POP3Transport *This = (POP3Transport *)iface;
00970 
00971     TRACE("()\n");
00972 
00973     InternetTransport_ChangeStatus(&This->InetTransport, IXP_DISCONNECTING);
00974 
00975     init_parser(This, POP3_QUIT, POP3_NONE);
00976     return InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvQUITResp);
00977 }
00978 
00979 static HRESULT WINAPI POP3Transport_CommandSTAT(IPOP3Transport *iface)
00980 {
00981     static char stat[] = "STAT\r\n";
00982     POP3Transport *This = (POP3Transport *)iface;
00983 
00984     TRACE("\n");
00985 
00986     init_parser(This, POP3_STAT, POP3_NONE);
00987     InternetTransport_DoCommand(&This->InetTransport, stat, POP3Transport_CallbackRecvSTATResp);
00988     return S_OK;
00989 }
00990 
00991 static HRESULT WINAPI POP3Transport_CommandNOOP(IPOP3Transport *iface)
00992 {
00993     static char noop[] = "NOOP\r\n";
00994     POP3Transport *This = (POP3Transport *)iface;
00995 
00996     TRACE("\n");
00997 
00998     init_parser(This, POP3_NOOP, POP3_NONE);
00999     InternetTransport_DoCommand(&This->InetTransport, noop, POP3Transport_CallbackRecvNOOPResp);
01000     return S_OK;
01001 }
01002 
01003 static HRESULT WINAPI POP3Transport_CommandRSET(IPOP3Transport *iface)
01004 {
01005     static char rset[] = "RSET\r\n";
01006     POP3Transport *This = (POP3Transport *)iface;
01007 
01008     TRACE("\n");
01009 
01010     init_parser(This, POP3_RSET, POP3_NONE);
01011     InternetTransport_DoCommand(&This->InetTransport, rset, POP3Transport_CallbackRecvRSETResp);
01012     return S_OK;
01013 }
01014 
01015 static HRESULT WINAPI POP3Transport_CommandUIDL(
01016     IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId)
01017 {
01018     static char uidl[] = "UIDL %u\r\n";
01019     static char uidl_all[] = "UIDL\r\n";
01020     POP3Transport *This = (POP3Transport *)iface;
01021     char *command;
01022     int len;
01023 
01024     TRACE("(%u, %u)\n", cmdtype, dwPopId);
01025 
01026     if (dwPopId)
01027     {
01028         len = sizeof(uidl) + 10 + 2; /* "4294967296" + "\r\n" */
01029         if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
01030         sprintf(command, uidl, dwPopId);
01031     }
01032     else command = uidl_all;
01033 
01034     init_parser(This, POP3_UIDL, cmdtype);
01035     InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvUIDLResp);
01036 
01037     if (dwPopId) HeapFree(GetProcessHeap(), 0, command);
01038     return S_OK;
01039 }
01040 
01041 static HRESULT WINAPI POP3Transport_CommandDELE(
01042     IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId)
01043 {
01044     static char dele[] = "DELE %u\r\n";
01045     POP3Transport *This = (POP3Transport *)iface;
01046     char *command;
01047     int len;
01048 
01049     TRACE("(%u, %u)\n", cmdtype, dwPopId);
01050 
01051     len = sizeof(dele) + 10 + 2; /* "4294967296" + "\r\n" */
01052     if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
01053     sprintf(command, dele, dwPopId);
01054 
01055     init_parser(This, POP3_DELE, cmdtype);
01056     InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvDELEResp);
01057 
01058     HeapFree(GetProcessHeap(), 0, command);
01059     return S_OK;
01060 }
01061 
01062 static HRESULT WINAPI POP3Transport_CommandRETR(
01063     IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId)
01064 {
01065     static char retr[] = "RETR %u\r\n";
01066     POP3Transport *This = (POP3Transport *)iface;
01067     char *command;
01068     int len;
01069 
01070     TRACE("(%u, %u)\n", cmdtype, dwPopId);
01071 
01072     len = sizeof(retr) + 10 + 2; /* "4294967296" + "\r\n" */
01073     if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
01074     sprintf(command, retr, dwPopId);
01075 
01076     init_parser(This, POP3_RETR, cmdtype);
01077     InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvRETRResp);
01078 
01079     HeapFree(GetProcessHeap(), 0, command);
01080     return S_OK;
01081 }
01082 
01083 static const IPOP3TransportVtbl POP3TransportVtbl =
01084 {
01085     POP3Transport_QueryInterface,
01086     POP3Transport_AddRef,
01087     POP3Transport_Release,
01088     POP3Transport_GetServerInfo,
01089     POP3Transport_GetIXPType,
01090     POP3Transport_IsState,
01091     POP3Transport_InetServerFromAccount,
01092     POP3Transport_Connect,
01093     POP3Transport_HandsOffCallback,
01094     POP3Transport_Disconnect,
01095     POP3Transport_DropConnection,
01096     POP3Transport_GetStatus,
01097     POP3Transport_InitNew,
01098     POP3Transport_MarkItem,
01099     POP3Transport_CommandAUTH,
01100     POP3Transport_CommandUSER,
01101     POP3Transport_CommandPASS,
01102     POP3Transport_CommandLIST,
01103     POP3Transport_CommandTOP,
01104     POP3Transport_CommandQUIT,
01105     POP3Transport_CommandSTAT,
01106     POP3Transport_CommandNOOP,
01107     POP3Transport_CommandRSET,
01108     POP3Transport_CommandUIDL,
01109     POP3Transport_CommandDELE,
01110     POP3Transport_CommandRETR
01111 };
01112 
01113 HRESULT WINAPI CreatePOP3Transport(IPOP3Transport **ppTransport)
01114 {
01115     HRESULT hr;
01116     POP3Transport *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
01117     if (!This)
01118         return E_OUTOFMEMORY;
01119 
01120     This->InetTransport.u.vtblPOP3 = &POP3TransportVtbl;
01121     This->refs = 0;
01122     hr = InternetTransport_Init(&This->InetTransport);
01123     if (FAILED(hr))
01124     {
01125         HeapFree(GetProcessHeap(), 0, This);
01126         return hr;
01127     }
01128 
01129     *ppTransport = (IPOP3Transport *)&This->InetTransport.u.vtblPOP3;
01130     IPOP3Transport_AddRef(*ppTransport);
01131 
01132     return S_OK;
01133 }
01134 
01135 static HRESULT WINAPI POP3TransportCF_QueryInterface(LPCLASSFACTORY iface,
01136     REFIID riid, LPVOID *ppv)
01137 {
01138     *ppv = NULL;
01139     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
01140     {
01141         *ppv = iface;
01142         IUnknown_AddRef(iface);
01143         return S_OK;
01144     }
01145     return E_NOINTERFACE;
01146 }
01147 
01148 static ULONG WINAPI POP3TransportCF_AddRef(LPCLASSFACTORY iface)
01149 {
01150     return 2; /* non-heap based object */
01151 }
01152 
01153 static ULONG WINAPI POP3TransportCF_Release(LPCLASSFACTORY iface)
01154 {
01155     return 1; /* non-heap based object */
01156 }
01157 
01158 static HRESULT WINAPI POP3TransportCF_CreateInstance(LPCLASSFACTORY iface,
01159     LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
01160 {
01161     HRESULT hr;
01162     IPOP3Transport *pPop3Transport;
01163 
01164     TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
01165 
01166     *ppv = NULL;
01167 
01168     if (pUnk)
01169         return CLASS_E_NOAGGREGATION;
01170 
01171     hr = CreatePOP3Transport(&pPop3Transport);
01172     if (FAILED(hr))
01173         return hr;
01174 
01175     hr = IPOP3Transport_QueryInterface(pPop3Transport, riid, ppv);
01176     IPOP3Transport_Release(pPop3Transport);
01177 
01178     return hr;
01179 }
01180 
01181 static HRESULT WINAPI POP3TransportCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
01182 {
01183     FIXME("(%d)\n",fLock);
01184     return S_OK;
01185 }
01186 
01187 static const IClassFactoryVtbl POP3TransportCFVtbl =
01188 {
01189     POP3TransportCF_QueryInterface,
01190     POP3TransportCF_AddRef,
01191     POP3TransportCF_Release,
01192     POP3TransportCF_CreateInstance,
01193     POP3TransportCF_LockServer
01194 };
01195 static const IClassFactoryVtbl *POP3TransportCF = &POP3TransportCFVtbl;
01196 
01197 HRESULT POP3TransportCF_Create(REFIID riid, LPVOID *ppv)
01198 {
01199     return IClassFactory_QueryInterface((IClassFactory *)&POP3TransportCF, riid, ppv);
01200 }

Generated on Fri May 25 2012 04:22:08 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.