push 9eb9af089d68d39110a91889d3a673043db63c4b
[wine/hacks.git] / dlls / inetcomm / pop3transport.c
blob30dd1877694b40409704b865c1e83868eb3b948b
1 /*
2 * POP3 Transport
4 * Copyright 2008 Hans Leidekker for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <stdarg.h>
24 #include <stdio.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winnt.h"
29 #include "winuser.h"
30 #include "objbase.h"
31 #include "mimeole.h"
32 #include "wine/debug.h"
34 #include "inetcomm_private.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
38 enum parse_state
40 STATE_NONE,
41 STATE_OK,
42 STATE_MULTILINE,
43 STATE_DONE
46 typedef struct
48 InternetTransport InetTransport;
49 ULONG refs;
50 POP3COMMAND command;
51 POP3CMDTYPE type;
52 char *response;
53 char *ptr;
54 enum parse_state state;
55 BOOL valid_info;
56 DWORD msgid;
57 DWORD preview_lines;
58 } POP3Transport;
60 static HRESULT parse_response(POP3Transport *This)
62 switch (This->state)
64 case STATE_NONE:
66 if (strlen(This->response) < 3)
68 WARN("parse error\n");
69 This->state = STATE_DONE;
70 return S_FALSE;
72 if (!memcmp(This->response, "+OK", 3))
74 This->ptr = This->response + 3;
75 This->state = STATE_OK;
76 return S_OK;
78 This->state = STATE_DONE;
79 return S_FALSE;
81 default: return S_OK;
85 static HRESULT parse_uidl_response(POP3Transport *This, POP3UIDL *uidl)
87 char *p;
89 uidl->dwPopId = 0;
90 uidl->pszUidl = NULL;
91 switch (This->state)
93 case STATE_OK:
95 if (This->type == POP3CMD_GET_POPID)
97 if ((p = strchr(This->ptr, ' ')))
99 while (*p == ' ') p++;
100 sscanf(p, "%u", &uidl->dwPopId);
101 if ((p = strchr(p, ' ')))
103 while (*p == ' ') p++;
104 uidl->pszUidl = p;
105 This->valid_info = TRUE;
108 This->state = STATE_DONE;
109 return S_OK;
111 This->state = STATE_MULTILINE;
112 return S_OK;
114 case STATE_MULTILINE:
116 if (This->response[0] == '.' && !This->response[1])
118 This->valid_info = FALSE;
119 This->state = STATE_DONE;
120 return S_OK;
122 sscanf(This->response, "%u", &uidl->dwPopId);
123 if ((p = strchr(This->response, ' ')))
125 while (*p == ' ') p++;
126 uidl->pszUidl = p;
127 This->valid_info = TRUE;
128 return S_OK;
131 default:
133 WARN("parse error\n");
134 This->state = STATE_DONE;
135 return S_FALSE;
140 static HRESULT parse_stat_response(POP3Transport *This, POP3STAT *stat)
142 char *p;
144 stat->cMessages = 0;
145 stat->cbMessages = 0;
146 switch (This->state)
148 case STATE_OK:
150 if ((p = strchr(This->ptr, ' ')))
152 while (*p == ' ') p++;
153 sscanf(p, "%u %u", &stat->cMessages, &stat->cbMessages);
154 This->valid_info = TRUE;
155 This->state = STATE_DONE;
156 return S_OK;
159 default:
161 WARN("parse error\n");
162 This->state = STATE_DONE;
163 return S_FALSE;
168 static HRESULT parse_list_response(POP3Transport *This, POP3LIST *list)
170 char *p;
172 list->dwPopId = 0;
173 list->cbSize = 0;
174 switch (This->state)
176 case STATE_OK:
178 if (This->type == POP3CMD_GET_POPID)
180 if ((p = strchr(This->ptr, ' ')))
182 while (*p == ' ') p++;
183 sscanf(p, "%u %u", &list->dwPopId, &list->cbSize);
184 This->valid_info = TRUE;
186 This->state = STATE_DONE;
187 return S_OK;
189 This->state = STATE_MULTILINE;
190 return S_OK;
192 case STATE_MULTILINE:
194 if (This->response[0] == '.' && !This->response[1])
196 This->valid_info = FALSE;
197 This->state = STATE_DONE;
198 return S_OK;
200 sscanf(This->response, "%u", &list->dwPopId);
201 if ((p = strchr(This->response, ' ')))
203 while (*p == ' ') p++;
204 sscanf(p, "%u", &list->cbSize);
205 This->valid_info = TRUE;
206 return S_OK;
209 default:
211 WARN("parse error\n");
212 This->state = STATE_DONE;
213 return S_FALSE;
218 static HRESULT parse_dele_response(POP3Transport *This, DWORD *dwPopId)
220 switch (This->state)
222 case STATE_OK:
224 *dwPopId = 0; /* FIXME */
225 This->state = STATE_DONE;
226 return S_OK;
228 default:
230 WARN("parse error\n");
231 This->state = STATE_DONE;
232 return S_FALSE;
237 static HRESULT parse_retr_response(POP3Transport *This, POP3RETR *retr)
239 switch (This->state)
241 case STATE_OK:
243 retr->fHeader = FALSE;
244 retr->fBody = FALSE;
245 retr->dwPopId = This->msgid;
246 retr->cbSoFar = 0;
247 retr->pszLines = This->response;
248 retr->cbLines = 0;
250 This->state = STATE_MULTILINE;
251 This->valid_info = FALSE;
252 return S_OK;
254 case STATE_MULTILINE:
256 int len;
258 if (This->response[0] == '.' && !This->response[1])
260 retr->cbLines = retr->cbSoFar;
261 This->state = STATE_DONE;
262 return S_OK;
264 retr->fHeader = TRUE;
265 if (!This->response[0]) retr->fBody = TRUE;
267 len = strlen(This->response);
268 retr->cbSoFar += len;
269 retr->pszLines = This->response;
270 retr->cbLines = len;
272 This->valid_info = TRUE;
273 return S_OK;
275 default:
277 WARN("parse error\n");
278 This->state = STATE_DONE;
279 return S_FALSE;
284 static HRESULT parse_top_response(POP3Transport *This, POP3TOP *top)
286 switch (This->state)
288 case STATE_OK:
290 top->fHeader = FALSE;
291 top->fBody = FALSE;
292 top->dwPopId = This->msgid;
293 top->cPreviewLines = This->preview_lines;
294 top->cbSoFar = 0;
295 top->pszLines = This->response;
296 top->cbLines = 0;
298 This->state = STATE_MULTILINE;
299 This->valid_info = FALSE;
300 return S_OK;
302 case STATE_MULTILINE:
304 int len;
306 if (This->response[0] == '.' && !This->response[1])
308 top->cbLines = top->cbSoFar;
309 This->state = STATE_DONE;
310 return S_OK;
312 top->fHeader = TRUE;
313 if (!This->response[0]) top->fBody = TRUE;
315 len = strlen(This->response);
316 top->cbSoFar += len;
317 top->pszLines = This->response;
318 top->cbLines = len;
320 This->valid_info = TRUE;
321 return S_OK;
323 default:
325 WARN("parse error\n");
326 This->state = STATE_DONE;
327 return S_FALSE;
332 static void init_parser(POP3Transport *This, POP3COMMAND command, POP3CMDTYPE type)
334 This->state = STATE_NONE;
335 This->command = command;
336 This->type = type;
339 static HRESULT POP3Transport_ParseResponse(POP3Transport *This, char *pszResponse, POP3RESPONSE *pResponse)
341 HRESULT hr;
343 TRACE("response: %s\n", debugstr_a(pszResponse));
345 This->response = pszResponse;
346 This->valid_info = FALSE;
347 TRACE("state %u\n", This->state);
349 if (SUCCEEDED((hr = parse_response(This))))
351 switch (This->command)
353 case POP3_UIDL: hr = parse_uidl_response(This, &pResponse->rUidlInfo); break;
354 case POP3_STAT: hr = parse_stat_response(This, &pResponse->rStatInfo); break;
355 case POP3_LIST: hr = parse_list_response(This, &pResponse->rListInfo); break;
356 case POP3_DELE: hr = parse_dele_response(This, &pResponse->dwPopId); break;
357 case POP3_RETR: hr = parse_retr_response(This, &pResponse->rRetrInfo); break;
358 case POP3_TOP: hr = parse_top_response(This, &pResponse->rTopInfo); break;
359 default:
360 This->state = STATE_DONE;
361 break;
364 pResponse->command = This->command;
365 pResponse->fDone = (This->state == STATE_DONE);
366 pResponse->fValidInfo = This->valid_info;
367 pResponse->rIxpResult.hrResult = hr;
368 pResponse->rIxpResult.pszResponse = pszResponse;
369 pResponse->rIxpResult.uiServerError = 0;
370 pResponse->rIxpResult.hrServerError = pResponse->rIxpResult.hrResult;
371 pResponse->rIxpResult.dwSocketError = WSAGetLastError();
372 pResponse->rIxpResult.pszProblem = NULL;
373 pResponse->pTransport = (IPOP3Transport *)&This->InetTransport.u.vtblPOP3;
375 if (This->InetTransport.pCallback && This->InetTransport.fCommandLogging)
377 ITransportCallback_OnCommand(This->InetTransport.pCallback, CMD_RESP,
378 pResponse->rIxpResult.pszResponse, pResponse->rIxpResult.hrServerError,
379 (IInternetTransport *)&This->InetTransport.u.vtbl);
381 return S_OK;
384 static void POP3Transport_CallbackProcessDELEResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
386 POP3Transport *This = (POP3Transport *)iface;
387 POP3RESPONSE response;
388 HRESULT hr;
390 TRACE("\n");
392 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
393 if (FAILED(hr))
395 /* FIXME: handle error */
396 return;
399 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
402 static void POP3Transport_CallbackRecvDELEResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
404 POP3Transport *This = (POP3Transport *)iface;
406 TRACE("\n");
407 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessDELEResp);
410 static void POP3Transport_CallbackProcessNOOPResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
412 POP3Transport *This = (POP3Transport *)iface;
413 POP3RESPONSE response;
414 HRESULT hr;
416 TRACE("\n");
418 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
419 if (FAILED(hr))
421 /* FIXME: handle error */
422 return;
425 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
428 static void POP3Transport_CallbackRecvNOOPResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
430 POP3Transport *This = (POP3Transport *)iface;
432 TRACE("\n");
433 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessNOOPResp);
436 static void POP3Transport_CallbackProcessRSETResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
438 POP3Transport *This = (POP3Transport *)iface;
439 POP3RESPONSE response;
440 HRESULT hr;
442 TRACE("\n");
444 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
445 if (FAILED(hr))
447 /* FIXME: handle error */
448 return;
451 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
454 static void POP3Transport_CallbackRecvRSETResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
456 POP3Transport *This = (POP3Transport *)iface;
458 TRACE("\n");
459 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessRSETResp);
462 void POP3Transport_CallbackProcessRETRResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
464 POP3Transport *This = (POP3Transport *)iface;
465 POP3RESPONSE response;
466 HRESULT hr;
468 TRACE("\n");
470 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
471 if (FAILED(hr))
473 /* FIXME: handle error */
474 return;
477 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
479 if (!response.fDone)
481 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessRETRResp);
482 return;
485 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
488 static void POP3Transport_CallbackRecvRETRResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
490 POP3Transport *This = (POP3Transport *)iface;
492 TRACE("\n");
493 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessRETRResp);
496 static void POP3Transport_CallbackProcessTOPResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
498 POP3Transport *This = (POP3Transport *)iface;
499 POP3RESPONSE response;
500 HRESULT hr;
502 TRACE("\n");
504 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
505 if (FAILED(hr))
507 /* FIXME: handle error */
508 return;
511 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
513 if (!response.fDone)
515 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessTOPResp);
516 return;
519 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
522 static void POP3Transport_CallbackRecvTOPResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
524 POP3Transport *This = (POP3Transport *)iface;
526 TRACE("\n");
527 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessTOPResp);
530 static void POP3Transport_CallbackProcessLISTResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
532 POP3Transport *This = (POP3Transport *)iface;
533 POP3RESPONSE response;
534 HRESULT hr;
536 TRACE("\n");
538 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
539 if (FAILED(hr))
541 /* FIXME: handle error */
542 return;
545 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
547 if (!response.fDone)
549 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessLISTResp);
550 return;
553 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
556 static void POP3Transport_CallbackRecvLISTResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
558 POP3Transport *This = (POP3Transport *)iface;
560 TRACE("\n");
561 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessLISTResp);
564 static void POP3Transport_CallbackProcessUIDLResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
566 POP3Transport *This = (POP3Transport *)iface;
567 POP3RESPONSE response;
568 HRESULT hr;
570 TRACE("\n");
572 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
573 if (FAILED(hr))
575 /* FIXME: handle error */
576 return;
579 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
581 if (!response.fDone)
583 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessUIDLResp);
584 return;
587 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
590 static void POP3Transport_CallbackRecvUIDLResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
592 POP3Transport *This = (POP3Transport *)iface;
594 TRACE("\n");
595 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessUIDLResp);
598 static void POP3Transport_CallbackProcessSTATResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
600 POP3Transport *This = (POP3Transport *)iface;
601 POP3RESPONSE response;
602 HRESULT hr;
604 TRACE("\n");
606 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
607 if (FAILED(hr))
609 /* FIXME: handle error */
610 return;
613 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
616 static void POP3Transport_CallbackRecvSTATResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
618 POP3Transport *This = (POP3Transport *)iface;
620 TRACE("\n");
621 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessSTATResp);
624 static void POP3Transport_CallbackProcessPASSResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
626 POP3Transport *This = (POP3Transport *)iface;
627 POP3RESPONSE response;
628 HRESULT hr;
630 TRACE("\n");
632 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
633 if (FAILED(hr))
635 /* FIXME: handle error */
636 return;
639 InternetTransport_ChangeStatus(&This->InetTransport, IXP_AUTHORIZED);
640 InternetTransport_ChangeStatus(&This->InetTransport, IXP_CONNECTED);
642 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
645 static void POP3Transport_CallbackRecvPASSResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
647 POP3Transport *This = (POP3Transport *)iface;
649 TRACE("\n");
650 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessPASSResp);
653 static void POP3Transport_CallbackProcessUSERResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
655 static char pass[] = "PASS ";
656 POP3Transport *This = (POP3Transport *)iface;
657 POP3RESPONSE response;
658 char *command;
659 int len;
660 HRESULT hr;
662 TRACE("\n");
664 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
665 if (FAILED(hr))
667 /* FIXME: handle error */
668 return;
671 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
673 len = sizeof(pass) + strlen(This->InetTransport.ServerInfo.szPassword) + 2; /* "\r\n" */
674 command = HeapAlloc(GetProcessHeap(), 0, len);
676 strcpy(command, pass);
677 strcat(command, This->InetTransport.ServerInfo.szPassword);
678 strcat(command, "\r\n");
680 init_parser(This, POP3_PASS, POP3_NONE);
682 InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvPASSResp);
683 HeapFree(GetProcessHeap(), 0, command);
686 static void POP3Transport_CallbackRecvUSERResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
688 POP3Transport *This = (POP3Transport *)iface;
690 TRACE("\n");
691 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessUSERResp);
694 static void POP3Transport_CallbackSendUSERCmd(IInternetTransport *iface, char *pBuffer, int cbBuffer)
696 static char user[] = "USER ";
697 POP3Transport *This = (POP3Transport *)iface;
698 char *command;
699 int len;
701 TRACE("\n");
703 len = sizeof(user) + strlen(This->InetTransport.ServerInfo.szUserName) + 2; /* "\r\n" */
704 command = HeapAlloc(GetProcessHeap(), 0, len);
706 strcpy(command, user);
707 strcat(command, This->InetTransport.ServerInfo.szUserName);
708 strcat(command, "\r\n");
709 InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvUSERResp);
711 HeapFree(GetProcessHeap(), 0, command);
714 static void POP3Transport_CallbackProcessQUITResponse(IInternetTransport *iface, char *pBuffer, int cbBuffer)
716 POP3Transport *This = (POP3Transport *)iface;
717 POP3RESPONSE response;
718 HRESULT hr;
720 TRACE("%s\n", debugstr_an(pBuffer, cbBuffer));
722 hr = POP3Transport_ParseResponse(This, pBuffer, &response);
723 if (FAILED(hr))
725 /* FIXME: handle error */
726 return;
729 IPOP3Callback_OnResponse((IPOP3Callback *)This->InetTransport.pCallback, &response);
730 InternetTransport_DropConnection(&This->InetTransport);
733 static void POP3Transport_CallbackRecvQUITResp(IInternetTransport *iface, char *pBuffer, int cbBuffer)
735 POP3Transport *This = (POP3Transport *)iface;
737 TRACE("\n");
738 InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackProcessQUITResponse);
741 static HRESULT WINAPI POP3Transport_QueryInterface(IPOP3Transport *iface, REFIID riid, void **ppv)
743 TRACE("(%s, %p)\n", debugstr_guid(riid), ppv);
745 if (IsEqualIID(riid, &IID_IUnknown) ||
746 IsEqualIID(riid, &IID_IInternetTransport) ||
747 IsEqualIID(riid, &IID_IPOP3Transport))
749 *ppv = iface;
750 IUnknown_AddRef(iface);
751 return S_OK;
753 *ppv = NULL;
754 FIXME("no interface for %s\n", debugstr_guid(riid));
755 return E_NOINTERFACE;
758 static ULONG WINAPI POP3Transport_AddRef(IPOP3Transport *iface)
760 POP3Transport *This = (POP3Transport *)iface;
761 return InterlockedIncrement((LONG *)&This->refs);
764 static ULONG WINAPI POP3Transport_Release(IPOP3Transport *iface)
766 POP3Transport *This = (POP3Transport *)iface;
767 ULONG refs = InterlockedDecrement((LONG *)&This->refs);
768 if (!refs)
770 TRACE("destroying %p\n", This);
771 if (This->InetTransport.Status != IXP_DISCONNECTED)
772 InternetTransport_DropConnection(&This->InetTransport);
773 if (This->InetTransport.pCallback) ITransportCallback_Release(This->InetTransport.pCallback);
774 HeapFree(GetProcessHeap(), 0, This);
776 return refs;
779 static HRESULT WINAPI POP3Transport_GetServerInfo(IPOP3Transport *iface,
780 LPINETSERVER pInetServer)
782 POP3Transport *This = (POP3Transport *)iface;
784 TRACE("(%p)\n", pInetServer);
785 return InternetTransport_GetServerInfo(&This->InetTransport, pInetServer);
788 static IXPTYPE WINAPI POP3Transport_GetIXPType(IPOP3Transport *iface)
790 TRACE("()\n");
791 return IXP_POP3;
794 static HRESULT WINAPI POP3Transport_IsState(IPOP3Transport *iface, IXPISSTATE isstate)
796 FIXME("(%u)\n", isstate);
797 return E_NOTIMPL;
800 static HRESULT WINAPI POP3Transport_InetServerFromAccount(
801 IPOP3Transport *iface, IImnAccount *pAccount, LPINETSERVER pInetServer)
803 POP3Transport *This = (POP3Transport *)iface;
805 TRACE("(%p, %p)\n", pAccount, pInetServer);
806 return InternetTransport_InetServerFromAccount(&This->InetTransport, pAccount, pInetServer);
809 static HRESULT WINAPI POP3Transport_Connect(IPOP3Transport *iface,
810 LPINETSERVER pInetServer, boolean fAuthenticate, boolean fCommandLogging)
812 POP3Transport *This = (POP3Transport *)iface;
813 HRESULT hr;
815 TRACE("(%p, %s, %s)\n", pInetServer, fAuthenticate ? "TRUE" : "FALSE", fCommandLogging ? "TRUE" : "FALSE");
817 hr = InternetTransport_Connect(&This->InetTransport, pInetServer, fAuthenticate, fCommandLogging);
818 if (FAILED(hr))
819 return hr;
821 init_parser(This, POP3_USER, POP3_NONE);
822 return InternetTransport_ReadLine(&This->InetTransport, POP3Transport_CallbackSendUSERCmd);
825 static HRESULT WINAPI POP3Transport_HandsOffCallback(IPOP3Transport *iface)
827 POP3Transport *This = (POP3Transport *)iface;
829 TRACE("()\n");
830 return InternetTransport_HandsOffCallback(&This->InetTransport);
833 static HRESULT WINAPI POP3Transport_Disconnect(IPOP3Transport *iface)
835 TRACE("()\n");
836 return IPOP3Transport_CommandQUIT(iface);
839 static HRESULT WINAPI POP3Transport_DropConnection(IPOP3Transport *iface)
841 POP3Transport *This = (POP3Transport *)iface;
843 TRACE("()\n");
844 return InternetTransport_DropConnection(&This->InetTransport);
847 static HRESULT WINAPI POP3Transport_GetStatus(IPOP3Transport *iface,
848 IXPSTATUS *pCurrentStatus)
850 POP3Transport *This = (POP3Transport *)iface;
852 TRACE("()\n");
853 return InternetTransport_GetStatus(&This->InetTransport, pCurrentStatus);
856 static HRESULT WINAPI POP3Transport_InitNew(IPOP3Transport *iface,
857 LPSTR pszLogFilePath, IPOP3Callback *pCallback)
859 POP3Transport *This = (POP3Transport *)iface;
861 TRACE("(%s, %p)\n", debugstr_a(pszLogFilePath), pCallback);
863 if (!pCallback)
864 return E_INVALIDARG;
866 if (pszLogFilePath)
867 FIXME("not using log file of %s, use Wine debug logging instead\n",
868 debugstr_a(pszLogFilePath));
870 IPOP3Callback_AddRef(pCallback);
871 This->InetTransport.pCallback = (ITransportCallback *)pCallback;
872 This->InetTransport.fInitialised = TRUE;
874 return S_OK;
877 static HRESULT WINAPI POP3Transport_MarkItem(IPOP3Transport *iface, POP3MARKTYPE marktype,
878 DWORD dwPopId, boolean fMarked)
880 FIXME("(%u, %u, %d)\n", marktype, dwPopId, fMarked);
881 return E_NOTIMPL;
884 static HRESULT WINAPI POP3Transport_CommandAUTH(IPOP3Transport *iface, LPSTR pszAuthType)
886 FIXME("(%s)\n", pszAuthType);
887 return E_NOTIMPL;
890 static HRESULT WINAPI POP3Transport_CommandUSER(IPOP3Transport *iface, LPSTR username)
892 static char user[] = "USER ";
893 POP3Transport *This = (POP3Transport *)iface;
894 char *command;
895 int len;
897 TRACE("(%s)\n", username);
899 len = sizeof(user) + strlen(username) + 2; /* "\r\n" */
900 if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
902 strcpy(command, user);
903 strcat(command, username);
904 strcat(command, "\r\n");
906 init_parser(This, POP3_USER, POP3_NONE);
907 InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvUSERResp);
909 HeapFree(GetProcessHeap(), 0, command);
910 return S_OK;
913 static HRESULT WINAPI POP3Transport_CommandPASS(IPOP3Transport *iface, LPSTR password)
915 static char pass[] = "PASS ";
916 POP3Transport *This = (POP3Transport *)iface;
917 char *command;
918 int len;
920 TRACE("(%p)\n", password);
922 len = sizeof(pass) + strlen(password) + 2; /* "\r\n" */
923 if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
925 strcpy(command, pass);
926 strcat(command, password);
927 strcat(command, "\r\n");
929 init_parser(This, POP3_PASS, POP3_NONE);
930 InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvPASSResp);
932 HeapFree(GetProcessHeap(), 0, command);
933 return S_OK;
936 static HRESULT WINAPI POP3Transport_CommandLIST(
937 IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId)
939 static char list[] = "LIST %u\r\n";
940 static char list_all[] = "LIST\r\n";
941 POP3Transport *This = (POP3Transport *)iface;
942 char *command;
943 int len;
945 TRACE("(%u, %u)\n", cmdtype, dwPopId);
947 if (dwPopId)
949 len = sizeof(list) + 10 + 2; /* "4294967296" + "\r\n" */
950 if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
951 sprintf(command, list, dwPopId);
953 else command = list_all;
955 init_parser(This, POP3_LIST, cmdtype);
956 InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvLISTResp);
958 if (dwPopId) HeapFree(GetProcessHeap(), 0, command);
959 return S_OK;
962 static HRESULT WINAPI POP3Transport_CommandTOP(
963 IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId, DWORD cPreviewLines)
965 static char top[] = "TOP %u %u\r\n";
966 POP3Transport *This = (POP3Transport *)iface;
967 char *command;
968 int len;
970 TRACE("(%u, %u, %u)\n", cmdtype, dwPopId, cPreviewLines);
972 len = sizeof(top) + 20 + 2; /* 2 * "4294967296" + "\r\n" */
973 if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
974 sprintf(command, top, dwPopId, cPreviewLines);
976 This->preview_lines = cPreviewLines;
977 init_parser(This, POP3_TOP, cmdtype);
978 InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvTOPResp);
980 HeapFree(GetProcessHeap(), 0, command);
981 return S_OK;
984 static HRESULT WINAPI POP3Transport_CommandQUIT(IPOP3Transport *iface)
986 static char command[] = "QUIT\r\n";
987 POP3Transport *This = (POP3Transport *)iface;
989 TRACE("()\n");
991 InternetTransport_ChangeStatus(&This->InetTransport, IXP_DISCONNECTING);
993 init_parser(This, POP3_QUIT, POP3_NONE);
994 return InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvQUITResp);
997 static HRESULT WINAPI POP3Transport_CommandSTAT(IPOP3Transport *iface)
999 static char stat[] = "STAT\r\n";
1000 POP3Transport *This = (POP3Transport *)iface;
1002 TRACE("\n");
1004 init_parser(This, POP3_STAT, POP3_NONE);
1005 InternetTransport_DoCommand(&This->InetTransport, stat, POP3Transport_CallbackRecvSTATResp);
1006 return S_OK;
1009 static HRESULT WINAPI POP3Transport_CommandNOOP(IPOP3Transport *iface)
1011 static char noop[] = "NOOP\r\n";
1012 POP3Transport *This = (POP3Transport *)iface;
1014 TRACE("\n");
1016 init_parser(This, POP3_NOOP, POP3_NONE);
1017 InternetTransport_DoCommand(&This->InetTransport, noop, POP3Transport_CallbackRecvNOOPResp);
1018 return S_OK;
1021 static HRESULT WINAPI POP3Transport_CommandRSET(IPOP3Transport *iface)
1023 static char rset[] = "RSET\r\n";
1024 POP3Transport *This = (POP3Transport *)iface;
1026 TRACE("\n");
1028 init_parser(This, POP3_RSET, POP3_NONE);
1029 InternetTransport_DoCommand(&This->InetTransport, rset, POP3Transport_CallbackRecvRSETResp);
1030 return S_OK;
1033 static HRESULT WINAPI POP3Transport_CommandUIDL(
1034 IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId)
1036 static char uidl[] = "UIDL %u\r\n";
1037 static char uidl_all[] = "UIDL\r\n";
1038 POP3Transport *This = (POP3Transport *)iface;
1039 char *command;
1040 int len;
1042 TRACE("(%u, %u)\n", cmdtype, dwPopId);
1044 if (dwPopId)
1046 len = sizeof(uidl) + 10 + 2; /* "4294967296" + "\r\n" */
1047 if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
1048 sprintf(command, uidl, dwPopId);
1050 else command = uidl_all;
1052 init_parser(This, POP3_UIDL, cmdtype);
1053 InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvUIDLResp);
1055 if (dwPopId) HeapFree(GetProcessHeap(), 0, command);
1056 return S_OK;
1059 static HRESULT WINAPI POP3Transport_CommandDELE(
1060 IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId)
1062 static char dele[] = "DELE %u\r\n";
1063 POP3Transport *This = (POP3Transport *)iface;
1064 char *command;
1065 int len;
1067 TRACE("(%u, %u)\n", cmdtype, dwPopId);
1069 len = sizeof(dele) + 10 + 2; /* "4294967296" + "\r\n" */
1070 if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
1071 sprintf(command, dele, dwPopId);
1073 init_parser(This, POP3_DELE, cmdtype);
1074 InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvDELEResp);
1076 HeapFree(GetProcessHeap(), 0, command);
1077 return S_OK;
1080 static HRESULT WINAPI POP3Transport_CommandRETR(
1081 IPOP3Transport *iface, POP3CMDTYPE cmdtype, DWORD dwPopId)
1083 static char retr[] = "RETR %u\r\n";
1084 POP3Transport *This = (POP3Transport *)iface;
1085 char *command;
1086 int len;
1088 TRACE("(%u, %u)\n", cmdtype, dwPopId);
1090 len = sizeof(retr) + 10 + 2; /* "4294967296" + "\r\n" */
1091 if (!(command = HeapAlloc(GetProcessHeap(), 0, len))) return S_FALSE;
1092 sprintf(command, retr, dwPopId);
1094 init_parser(This, POP3_RETR, cmdtype);
1095 InternetTransport_DoCommand(&This->InetTransport, command, POP3Transport_CallbackRecvRETRResp);
1097 HeapFree(GetProcessHeap(), 0, command);
1098 return S_OK;
1101 static const IPOP3TransportVtbl POP3TransportVtbl =
1103 POP3Transport_QueryInterface,
1104 POP3Transport_AddRef,
1105 POP3Transport_Release,
1106 POP3Transport_GetServerInfo,
1107 POP3Transport_GetIXPType,
1108 POP3Transport_IsState,
1109 POP3Transport_InetServerFromAccount,
1110 POP3Transport_Connect,
1111 POP3Transport_HandsOffCallback,
1112 POP3Transport_Disconnect,
1113 POP3Transport_DropConnection,
1114 POP3Transport_GetStatus,
1115 POP3Transport_InitNew,
1116 POP3Transport_MarkItem,
1117 POP3Transport_CommandAUTH,
1118 POP3Transport_CommandUSER,
1119 POP3Transport_CommandPASS,
1120 POP3Transport_CommandLIST,
1121 POP3Transport_CommandTOP,
1122 POP3Transport_CommandQUIT,
1123 POP3Transport_CommandSTAT,
1124 POP3Transport_CommandNOOP,
1125 POP3Transport_CommandRSET,
1126 POP3Transport_CommandUIDL,
1127 POP3Transport_CommandDELE,
1128 POP3Transport_CommandRETR
1131 HRESULT WINAPI CreatePOP3Transport(IPOP3Transport **ppTransport)
1133 HRESULT hr;
1134 POP3Transport *This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1135 if (!This)
1136 return E_OUTOFMEMORY;
1138 This->InetTransport.u.vtblPOP3 = &POP3TransportVtbl;
1139 This->refs = 0;
1140 hr = InternetTransport_Init(&This->InetTransport);
1141 if (FAILED(hr))
1143 HeapFree(GetProcessHeap(), 0, This);
1144 return hr;
1147 *ppTransport = (IPOP3Transport *)&This->InetTransport.u.vtblPOP3;
1148 IPOP3Transport_AddRef(*ppTransport);
1150 return S_OK;
1153 static HRESULT WINAPI POP3TransportCF_QueryInterface(LPCLASSFACTORY iface,
1154 REFIID riid, LPVOID *ppv)
1156 *ppv = NULL;
1157 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassFactory))
1159 *ppv = iface;
1160 IUnknown_AddRef(iface);
1161 return S_OK;
1163 return E_NOINTERFACE;
1166 static ULONG WINAPI POP3TransportCF_AddRef(LPCLASSFACTORY iface)
1168 return 2; /* non-heap based object */
1171 static ULONG WINAPI POP3TransportCF_Release(LPCLASSFACTORY iface)
1173 return 1; /* non-heap based object */
1176 static HRESULT WINAPI POP3TransportCF_CreateInstance(LPCLASSFACTORY iface,
1177 LPUNKNOWN pUnk, REFIID riid, LPVOID *ppv)
1179 HRESULT hr;
1180 IPOP3Transport *pPop3Transport;
1182 TRACE("(%p, %s, %p)\n", pUnk, debugstr_guid(riid), ppv);
1184 *ppv = NULL;
1186 if (pUnk)
1187 return CLASS_E_NOAGGREGATION;
1189 hr = CreatePOP3Transport(&pPop3Transport);
1190 if (FAILED(hr))
1191 return hr;
1193 hr = IPOP3Transport_QueryInterface(pPop3Transport, riid, ppv);
1194 IPOP3Transport_Release(pPop3Transport);
1196 return hr;
1199 static HRESULT WINAPI POP3TransportCF_LockServer(LPCLASSFACTORY iface, BOOL fLock)
1201 FIXME("(%d)\n",fLock);
1202 return S_OK;
1205 static const IClassFactoryVtbl POP3TransportCFVtbl =
1207 POP3TransportCF_QueryInterface,
1208 POP3TransportCF_AddRef,
1209 POP3TransportCF_Release,
1210 POP3TransportCF_CreateInstance,
1211 POP3TransportCF_LockServer
1213 static const IClassFactoryVtbl *POP3TransportCF = &POP3TransportCFVtbl;
1215 HRESULT POP3TransportCF_Create(REFIID riid, LPVOID *ppv)
1217 return IClassFactory_QueryInterface((IClassFactory *)&POP3TransportCF, riid, ppv);