mirror of
https://github.com/azure-rtos/netx.git
synced 2023-08-10 07:57:54 +08:00
3067 lines
148 KiB
C
3067 lines
148 KiB
C
/**************************************************************************/
|
|
/* */
|
|
/* Copyright (c) Microsoft Corporation. All rights reserved. */
|
|
/* */
|
|
/* This software is licensed under the Microsoft Software License */
|
|
/* Terms for Microsoft Azure RTOS. Full text of the license can be */
|
|
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
|
|
/* and in the root directory of this software. */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
/** */
|
|
/** NetX POP3 Client Component */
|
|
/** */
|
|
/** Post Office Protocol Version 3 (POP3) */
|
|
/** */
|
|
/**************************************************************************/
|
|
/**************************************************************************/
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* APPLICATION INTERFACE DEFINITION RELEASE */
|
|
/* */
|
|
/* nx_pop3_client.c PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This file defines the NetX Post Office Protocol (POP3) */
|
|
/* Client component, including all data types and external references. */
|
|
/* It is assumed that tx_api.h, tx_port.h, nx_api.h, and nx_port.h, */
|
|
/* have already been included. */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
|
|
#define NX_POP3_CLIENT_SOURCE_CODE
|
|
|
|
/* Force error checking to be disabled in this module */
|
|
|
|
#ifndef NX_DISABLE_ERROR_CHECKING
|
|
#define NX_DISABLE_ERROR_CHECKING
|
|
#endif
|
|
|
|
|
|
#include "nx_api.h"
|
|
#include "nx_md5.h"
|
|
#include "nx_ip.h"
|
|
#include "nx_pop3_client.h"
|
|
#include <ctype.h>
|
|
|
|
/* The following array of state handlers is indexed by the state. */
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nxe_pop3_client_create PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function performs error checking on the create POP3 client */
|
|
/* service (IPv4 only). */
|
|
/* */
|
|
/* Note: The string lengths of client_name and client_password are */
|
|
/* limited by internal buffer size. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* APOP_authentication 1=enable APOP; 0=disable APOP */
|
|
/* ip_ptr Pointer to client IP instance */
|
|
/* packet_pool_ptr Pointer to client packet pool */
|
|
/* server_ip_address POP3 server IP address */
|
|
/* server_port POP3 server port */
|
|
/* client_name Client POP3 user name */
|
|
/* client_password Client POP3 password */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nx_pop3_client_create Creates the POP3 client */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nxe_pop3_client_create(NX_POP3_CLIENT *client_ptr, UINT APOP_authentication, NX_IP *ip_ptr,
|
|
NX_PACKET_POOL *packet_pool_ptr, ULONG server_ip_address, ULONG server_port, CHAR *client_name,
|
|
CHAR *client_password)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
|
|
/* Check for valid input pointers. */
|
|
if ((ip_ptr == NX_NULL) || (client_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL) || (client_name == NX_NULL) ||
|
|
(client_password == NX_NULL))
|
|
{
|
|
|
|
/* Return pointer error. */
|
|
return(NX_PTR_ERROR);
|
|
}
|
|
|
|
if ((ip_ptr -> nx_ip_id != NX_IP_ID) || (server_ip_address == 0) || (server_port == 0))
|
|
{
|
|
|
|
return NX_POP3_PARAM_ERROR;
|
|
}
|
|
|
|
/* Call the actual client create service. */
|
|
status = _nx_pop3_client_create(client_ptr,
|
|
APOP_authentication,
|
|
ip_ptr, packet_pool_ptr,
|
|
server_ip_address, server_port, client_name,
|
|
client_password);
|
|
|
|
/* Return completion status. */
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_create PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function creates a POP3 Client on the specified IP instance. */
|
|
/* */
|
|
/* Note: The string lengths of client_name and client_password are */
|
|
/* limited by internal buffer size. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* APOP_authentication 1=enable APOP; 0=disable APOP */
|
|
/* ip_ptr Pointer to client IP instance */
|
|
/* packet_pool_ptr Pointer to client packet pool */
|
|
/* server_ip_address POP3 server IP address */
|
|
/* server_port POP3 server port */
|
|
/* client_name Client POP3 user name */
|
|
/* client_password Client POP3 password */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_SUCCESS Successful completion status */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* nx_tcp_socket_create NetX TCP socket create service */
|
|
/* _nx_pop3_client_connect Connect POP3 Client to Server */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
|
|
/* verified memcpy use cases, */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_create(NX_POP3_CLIENT *client_ptr, UINT APOP_authentication, NX_IP *ip_ptr,
|
|
NX_PACKET_POOL *packet_pool_ptr, ULONG server_ip_address, ULONG server_port, CHAR *client_name,
|
|
CHAR *client_password)
|
|
|
|
{
|
|
|
|
UINT status;
|
|
UINT client_name_length;
|
|
UINT client_password_length;
|
|
|
|
|
|
client_ptr -> nx_pop3_client_ready_to_download = NX_FALSE;
|
|
|
|
if (_nx_utility_string_length_check(client_name, &client_name_length, NX_POP3_MAX_USERNAME) ||
|
|
_nx_utility_string_length_check(client_password, &client_password_length, NX_POP3_MAX_PASSWORD))
|
|
{
|
|
|
|
return NX_POP3_PARAM_ERROR;
|
|
}
|
|
|
|
/* Null the members of NX_POP3_CLIENT. */
|
|
memset(client_ptr, 0, sizeof(NX_POP3_CLIENT));
|
|
|
|
/* Configure Client identification. */
|
|
memset(client_ptr -> nx_pop3_client_name, 0, NX_POP3_MAX_USERNAME);
|
|
memcpy(client_ptr -> nx_pop3_client_name, client_name, client_name_length); /* Use case of memcpy is verified. */
|
|
memset(client_ptr -> nx_pop3_client_password, 0, NX_POP3_MAX_PASSWORD);
|
|
memcpy(client_ptr -> nx_pop3_client_password, client_password, client_password_length); /* Use case of memcpy is verified. */
|
|
|
|
/* Configure Client POP3 authentication options. */
|
|
client_ptr -> nx_pop3_client_enable_APOP_authentication = APOP_authentication;
|
|
|
|
/* Create a tcp socket to send/receive POP3 data. */
|
|
status = nx_tcp_socket_create(ip_ptr, &client_ptr -> nx_pop3_client_tcp_socket, "POP3 Client socket",
|
|
NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE,
|
|
NX_POP3_CLIENT_TCP_WINDOW_SIZE,
|
|
NX_NULL, NX_NULL);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error status. */
|
|
return(status);
|
|
}
|
|
|
|
/* Configure Client NetX and TCP/IP options. */
|
|
client_ptr -> nx_pop3_client_packet_pool_ptr = packet_pool_ptr;
|
|
|
|
status = _nx_pop3_client_connect(client_ptr, server_ip_address, server_port);
|
|
|
|
/* Return successful completion status. */
|
|
return(status);
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nxe_pop3_client_delete PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function performs error checking on the POP3 Client delete */
|
|
/* service. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer input */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nx_pop3_client_delete Actual Client delete service */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nxe_pop3_client_delete(NX_POP3_CLIENT *client_ptr)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
|
|
/* Check for valid input parameter. */
|
|
if (client_ptr == NX_NULL)
|
|
{
|
|
|
|
/* Return error status. */
|
|
return(NX_PTR_ERROR);
|
|
}
|
|
|
|
/* Call client create function. */
|
|
status = _nx_pop3_client_delete(client_ptr);
|
|
|
|
/* Return completion status. */
|
|
return(status);
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_delete PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function deletes the specified POP3 Client. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_SUCCESS Successful completion status */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* nx_tcp_socket_disconnect Closes the TCP connection */
|
|
/* nx_tcp_client_socket_unbind Releases (unbinds) the TCP port */
|
|
/* nx_tcp_socket_delete Deletes unbound TCP socket */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_delete(NX_POP3_CLIENT *client_ptr)
|
|
{
|
|
|
|
if (client_ptr -> nx_pop3_client_message_ptr)
|
|
{
|
|
nx_packet_release(client_ptr -> nx_pop3_client_message_ptr);
|
|
}
|
|
|
|
/* Yes, so disconnect client socket from server. */
|
|
nx_tcp_socket_disconnect(&client_ptr -> nx_pop3_client_tcp_socket, NX_POP3_CLIENT_DISCONNECT_TIMEOUT);
|
|
|
|
/* Unbind the port from client socket. */
|
|
nx_tcp_client_socket_unbind(&client_ptr -> nx_pop3_client_tcp_socket);
|
|
|
|
/* Release client socket. */
|
|
nx_tcp_socket_delete(&client_ptr -> nx_pop3_client_tcp_socket);
|
|
|
|
/* Clear the members of NX_POP3_CLIENT. */
|
|
memset(client_ptr, 0, sizeof(NX_POP3_CLIENT));
|
|
|
|
/* Return completion status. */
|
|
return(NX_SUCCESS);
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nxe_pop3_client_mail_items_get PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function performs error checking for the get mail items in */
|
|
/* client mailbox service. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* number_mail_items Pointer to items in mailbox */
|
|
/* maildrop_total_size Pointer to total mailbox size */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nxe_pop3_client_mail_items_get Actual get mail items service */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nxe_pop3_client_mail_items_get(NX_POP3_CLIENT *client_ptr, UINT *number_mail_items, ULONG *maildrop_total_size)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
|
|
/* Check for invalid pointer inpu. */
|
|
if ((client_ptr == NX_NULL) || (number_mail_items == NX_NULL) || (maildrop_total_size == NX_NULL))
|
|
{
|
|
|
|
return NX_PTR_ERROR;
|
|
}
|
|
|
|
status = _nx_pop3_client_mail_items_get(client_ptr, number_mail_items, maildrop_total_size);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_mail_items_get PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function retrieves the number of items and total size in bytes */
|
|
/* of mail data in the Client's mailbox. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* number_mail_items Pointer to items in mailbox */
|
|
/* maildrop_total_size Pointer to total mailbox size */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
|
|
/* Packet too small for command */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* nx_packet_allocate Allocate packet from packet pool */
|
|
/* nx_packet_release Release packet back to pool */
|
|
/* nx_tcp_socket_send Send packet out TCP socket */
|
|
/* nx_tcp_socket_receive Retrieve packet from TCP socket */
|
|
/* _nx_pop3_parse_response Extract word from server response */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
|
|
/* verified memcpy use cases, */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_mail_items_get(NX_POP3_CLIENT *client_ptr, UINT *number_mail_items, ULONG *maildrop_total_size)
|
|
{
|
|
|
|
UINT status;
|
|
NX_PACKET *packet_ptr, *recv_packet_ptr;
|
|
CHAR *buffer;
|
|
CHAR argument[10];
|
|
UINT packet_type;
|
|
|
|
packet_type = NX_TCP_PACKET;
|
|
|
|
/* Allocate a packet. */
|
|
status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
|
|
&packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Check for sufficient packet buffer size for command. */
|
|
if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_STAT) - 1) + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= packet_ptr -> nx_packet_data_end)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
/* Send the STAT command. */
|
|
buffer = (CHAR *)(packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
memcpy(buffer, NX_POP3_COMMAND_STAT, (sizeof(NX_POP3_COMMAND_STAT) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length = (sizeof(NX_POP3_COMMAND_STAT) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_STAT) - 1);
|
|
buffer += (sizeof(NX_POP3_COMMAND_STAT) - 1);
|
|
|
|
memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
buffer += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
|
|
/* Send the packet out. */
|
|
status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Clear existing Client maildrop data. */
|
|
client_ptr -> nx_pop3_client_total_message_size = 0;
|
|
client_ptr -> nx_pop3_client_maildrop_items = 0;
|
|
|
|
/* Receive server reply. */
|
|
status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error condition. */
|
|
return(status);
|
|
}
|
|
|
|
if (recv_packet_ptr -> nx_packet_next)
|
|
{
|
|
|
|
/* Chained packet is not supported. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
return(NX_INVALID_PACKET);
|
|
}
|
|
|
|
/* Set a pointer to the packet data. */
|
|
buffer = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Parse the first argument of the server reply. */
|
|
_nx_pop3_parse_response(buffer, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Initialize status to server error received. */
|
|
status = NX_POP3_SERVER_ERROR_STATUS;
|
|
|
|
/* Did the server accept the Client command? */
|
|
if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
|
|
{
|
|
|
|
/* Yes. Clear memory for parsing the mail item count. */
|
|
memset(argument, 0, 5);
|
|
|
|
/* Get the number of messages. */
|
|
_nx_pop3_parse_response(buffer, 2, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Check if argument parsed successfully. */
|
|
if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
|
|
{
|
|
|
|
/* It was; update session maildrop items. */
|
|
client_ptr -> nx_pop3_client_maildrop_items = strtoul(argument, NULL, 10);
|
|
|
|
/* Get total mail message data next. */
|
|
memset(argument, 0, 5);
|
|
|
|
/* Get the size in bytes of message data. */
|
|
_nx_pop3_parse_response(buffer, 3, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Check if argument parsed successfully. */
|
|
if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
|
|
{
|
|
|
|
/* It was; update total message data. */
|
|
client_ptr -> nx_pop3_client_total_message_size = strtoul(argument, NULL, 10);
|
|
|
|
status = NX_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
|
|
*maildrop_total_size = client_ptr -> nx_pop3_client_total_message_size;
|
|
*number_mail_items = client_ptr -> nx_pop3_client_maildrop_items;
|
|
|
|
nx_packet_release(recv_packet_ptr);
|
|
|
|
/* Return completion status. */
|
|
return status;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nxe_pop3_client_get_mail_item PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function performs error checking for the get mail item size */
|
|
/* service. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* mail_item Index into POP3 mailbox */
|
|
/* item_size Pointer to mail size */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nx_pop3_client_get_mail_size Actual get mail size service */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nxe_pop3_client_mail_item_size_get(NX_POP3_CLIENT *client_ptr, UINT mail_item, ULONG *size)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
|
|
/* Check for invalid pointer input. */
|
|
if ((client_ptr == NX_NULL) || (size == NX_NULL))
|
|
{
|
|
|
|
return NX_PTR_ERROR;
|
|
}
|
|
|
|
/* Check for an invalid index. */
|
|
if (mail_item == 0)
|
|
{
|
|
return NX_POP3_CLIENT_INVALID_INDEX;
|
|
}
|
|
|
|
status = _nx_pop3_client_mail_item_size_get(client_ptr, mail_item, size);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_mail_item_size_get PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function sends a LIST command for the specified mail item and */
|
|
/* processes the server response for size of the requested item. Note */
|
|
/* that there is considerable discrepancy between reported size and */
|
|
/* actual size, with the reported size usually 15% or more larger than */
|
|
/* actual. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* mail_item Index into POP3 mailbox */
|
|
/* size Pointer to mail item size */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
|
|
/* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
|
|
/* Packet too small for command */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* nx_packet_allocate Allocate packet from packet pool */
|
|
/* nx_packet_release Release packet back to pool */
|
|
/* nx_tcp_socket_send Send packet out TCP socket */
|
|
/* nx_tcp_socket_receive Retrieve packet from TCP socket */
|
|
/* _nx_pop3_parse_response Extract word from server response */
|
|
/* _nx_pop3_server_number_convert Convert integer to ascii */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
|
|
/* verified memcpy use cases, */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_mail_item_size_get(NX_POP3_CLIENT *client_ptr, UINT mail_item, ULONG *size)
|
|
{
|
|
|
|
NX_PACKET *packet_ptr, *recv_packet_ptr;
|
|
CHAR *buffer_ptr;
|
|
UINT num_size;
|
|
UINT status;
|
|
CHAR argument[10];
|
|
UINT packet_type;
|
|
|
|
|
|
/* Initialize mail box to having zero items. */
|
|
*size = 0;
|
|
|
|
/* Verify mail_item is valid index (less than total number items in mailbox. */
|
|
if (mail_item > client_ptr -> nx_pop3_client_maildrop_items)
|
|
{
|
|
return NX_POP3_INVALID_MAIL_ITEM;
|
|
}
|
|
|
|
packet_type = NX_TCP_PACKET;
|
|
|
|
/* Allocate a packet. */
|
|
status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
|
|
&packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
num_size = _nx_pop3_server_number_convert(mail_item, &argument[0]);
|
|
|
|
/* Determine if the packet payload is large enough for LIST command. */
|
|
if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_LIST) - 1) + 1 +
|
|
num_size + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= packet_ptr -> nx_packet_data_end)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
buffer_ptr = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
|
|
|
|
/* Send LIST mail_item query to server */
|
|
memcpy(buffer_ptr, NX_POP3_COMMAND_LIST, (sizeof(NX_POP3_COMMAND_LIST) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length = (sizeof(NX_POP3_COMMAND_LIST) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_LIST) - 1);
|
|
buffer_ptr += (sizeof(NX_POP3_COMMAND_LIST) - 1);
|
|
|
|
memcpy(buffer_ptr, " ", 1); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length++;
|
|
packet_ptr -> nx_packet_append_ptr++;
|
|
buffer_ptr++;
|
|
|
|
memcpy(buffer_ptr, &argument[0], num_size); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += num_size;
|
|
packet_ptr -> nx_packet_append_ptr += num_size;
|
|
buffer_ptr += num_size;
|
|
|
|
memcpy(buffer_ptr, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
buffer_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
|
|
/* Send the packet out. */
|
|
status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Receive server reply over session socket. */
|
|
status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error condition. */
|
|
return(status);
|
|
}
|
|
|
|
if (recv_packet_ptr -> nx_packet_next)
|
|
{
|
|
|
|
/* Chained packet is not supported. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
return(NX_INVALID_PACKET);
|
|
}
|
|
|
|
/* Set a pointer to the packet data. */
|
|
buffer_ptr = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Initialize status to bad reply error condition. */
|
|
status = NX_POP3_SERVER_ERROR_STATUS;
|
|
|
|
/* Parse the first argument of the server reply. */
|
|
_nx_pop3_parse_response(buffer_ptr, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Did the server accept the Client command? */
|
|
if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
|
|
{
|
|
|
|
/* Clear memory for parsing the mail item count. */
|
|
memset(argument, 0, 5);
|
|
|
|
/* Extact the message size. */
|
|
_nx_pop3_parse_response(buffer_ptr, 2, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Check if argument parsed successfully. */
|
|
if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
|
|
{
|
|
|
|
/* It was; verify it matches the input mail index. */
|
|
UINT server_maildrop_items = strtoul(argument, NULL, 10);
|
|
|
|
if (mail_item == server_maildrop_items)
|
|
{
|
|
|
|
/* It does. Parse the message size. */
|
|
_nx_pop3_parse_response(buffer_ptr, 3, recv_packet_ptr -> nx_packet_length,
|
|
(CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
|
|
{
|
|
|
|
*size = strtoul(argument, NULL, 10);
|
|
|
|
status = NX_SUCCESS;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Done with the server response, delete the packet. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
|
|
return status;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nxe_pop3_client_mail_item_get PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function performs error checking for the get mail item */
|
|
/* service. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* mail_item Index into POP3 mailbox */
|
|
/* item_size Pointer to mail size */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nx_pop3_client_mail_item_get Actual get mail service */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nxe_pop3_client_mail_item_get(NX_POP3_CLIENT *client_ptr, UINT mail_item, ULONG *item_size)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
/* Check for invalid pointer input. */
|
|
if ((client_ptr == NX_NULL) || (item_size == NX_NULL))
|
|
{
|
|
|
|
return NX_PTR_ERROR;
|
|
}
|
|
|
|
/* Check for an invalid index. */
|
|
if (mail_item == 0)
|
|
{
|
|
return NX_POP3_CLIENT_INVALID_INDEX;
|
|
}
|
|
|
|
status = _nx_pop3_client_mail_item_get(client_ptr, mail_item, item_size);
|
|
|
|
return status;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_mail_item_get PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function sends the RETR command to the server for the specified*/
|
|
/* mail item, and returns the server response. If accepted, it will */
|
|
/* parse the mail item size as well. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* mail_item Index into POP3 mailbox */
|
|
/* item_size Pointer to mail size */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
|
|
/* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
|
|
/* Packet too small for command */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* nx_packet_allocate Allocate packet from packet pool */
|
|
/* nx_packet_release Release packet back to pool */
|
|
/* nx_tcp_socket_send Send packet out TCP socket */
|
|
/* nx_tcp_socket_receive Retrieve packet from TCP socket */
|
|
/* _nx_pop3_parse_response Extract word from server response */
|
|
/* _nx_pop3_server_number_convert Convert integer to ascii */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
|
|
/* verified memcpy use cases, */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_mail_item_get(NX_POP3_CLIENT *client_ptr, UINT mail_item, ULONG *item_size)
|
|
{
|
|
|
|
UINT status;
|
|
UINT size;
|
|
NX_PACKET *packet_ptr, *recv_packet_ptr;
|
|
CHAR *buffer;
|
|
CHAR argument[10];
|
|
UINT packet_type;
|
|
|
|
|
|
client_ptr -> nx_pop3_client_ready_to_download = NX_FALSE;
|
|
|
|
/* Verify mail_item is valid index (less than total number items in mailbox. */
|
|
if (mail_item > client_ptr -> nx_pop3_client_maildrop_items)
|
|
{
|
|
return NX_POP3_INVALID_MAIL_ITEM;
|
|
}
|
|
|
|
/* Allocate a packet. */
|
|
packet_type = NX_TCP_PACKET;
|
|
|
|
/* Allocate a packet. */
|
|
status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
|
|
&packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Check packet payload can hold the Client message. . */
|
|
if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_RETR) - 1) + 1) >= packet_ptr -> nx_packet_data_end)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
buffer = (CHAR *)(packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Send a RETR command to the server. */
|
|
memcpy(packet_ptr -> nx_packet_prepend_ptr, NX_POP3_COMMAND_RETR, (sizeof(NX_POP3_COMMAND_RETR) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_RETR) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_RETR) - 1);
|
|
buffer += (sizeof(NX_POP3_COMMAND_RETR) - 1);
|
|
|
|
memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length++;
|
|
packet_ptr -> nx_packet_append_ptr++;
|
|
buffer++;
|
|
|
|
/* Convert the mail item index to ascii. */
|
|
size = _nx_pop3_server_number_convert(mail_item, &argument[0]);
|
|
if ((buffer + size + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= (CHAR *)packet_ptr -> nx_packet_data_end)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
memcpy(buffer, &argument[0], size); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += size;
|
|
packet_ptr -> nx_packet_append_ptr += size;
|
|
buffer += size;
|
|
|
|
memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
buffer += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
|
|
/* Send the packet out. */
|
|
status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Receive server reply over Client socket. */
|
|
status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error condition. */
|
|
return(status);
|
|
}
|
|
|
|
if (recv_packet_ptr -> nx_packet_next)
|
|
{
|
|
|
|
/* Chained packet is not supported. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
return(NX_INVALID_PACKET);
|
|
}
|
|
|
|
/* Set a pointer to the packet data. */
|
|
buffer = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Parse the first argument of the server reply. */
|
|
_nx_pop3_parse_response(buffer, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument,
|
|
sizeof(argument), NX_FALSE, NX_FALSE);
|
|
|
|
/* Did the server accept the Client command? */
|
|
if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
|
|
{
|
|
|
|
client_ptr -> nx_pop3_client_ready_to_download = NX_TRUE;
|
|
*item_size = 0;
|
|
|
|
/* Yes. Clear memory for parsing the mail item size. */
|
|
memset(argument, 0, sizeof(argument));
|
|
|
|
/* Get the number of szie of the message. . */
|
|
_nx_pop3_parse_response(buffer, 2, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument,
|
|
sizeof(argument) - 1, NX_FALSE, NX_FALSE);
|
|
|
|
/* Check if argument parsed successfully. */
|
|
if ((argument[0] >= 0x30) && (argument[0] <= 0x39))
|
|
{
|
|
|
|
/* It was; set the size of th e mail item. */
|
|
*item_size = strtoul(argument, NULL, 10);
|
|
}
|
|
|
|
while (((ULONG)buffer < ((ULONG)recv_packet_ptr -> nx_packet_append_ptr - 1)) &&
|
|
((*buffer != 0x0D) || (*(buffer + 1) != 0x0A)))
|
|
{
|
|
buffer++;
|
|
}
|
|
|
|
buffer += 2;
|
|
|
|
if ((UCHAR *)buffer == recv_packet_ptr -> nx_packet_append_ptr)
|
|
{
|
|
nx_packet_release(recv_packet_ptr);
|
|
}
|
|
else
|
|
{
|
|
client_ptr -> nx_pop3_client_message_ptr = recv_packet_ptr;
|
|
recv_packet_ptr -> nx_packet_length -=
|
|
(ULONG)buffer - (ULONG)recv_packet_ptr -> nx_packet_prepend_ptr;
|
|
recv_packet_ptr -> nx_packet_prepend_ptr = (UCHAR *)buffer;
|
|
}
|
|
|
|
return NX_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
nx_packet_release(recv_packet_ptr);
|
|
return NX_POP3_SERVER_ERROR_STATUS;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nxe_pop3_client_mail_item_message_get PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function performs error checking for the get message data */
|
|
/* service. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* recv_packet_ptr Pointer to received PP3 packet */
|
|
/* bytes_retrieved Size of message data in packet */
|
|
/* final_packet Indicates if last packet */
|
|
/* NX_FALSE = not the last packet */
|
|
/* NX_TRUE = is the last packet */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nx_pop3_client_mail_item_message_data_get */
|
|
/* Actual get message data service */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nxe_pop3_client_mail_item_message_get(NX_POP3_CLIENT *client_ptr, NX_PACKET **recv_packet_ptr, ULONG *bytes_retrieved, UINT *final_packet)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
|
|
if ((client_ptr == NX_NULL) || (recv_packet_ptr == NX_NULL) || (bytes_retrieved == NX_NULL) || (final_packet == NX_NULL))
|
|
{
|
|
|
|
return NX_PTR_ERROR;
|
|
}
|
|
|
|
status = _nx_pop3_client_mail_item_message_get(client_ptr, recv_packet_ptr, bytes_retrieved, final_packet);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_mail_item_message_get PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function retrieves message packets from the POP3 Client TCP */
|
|
/* socket and returns them to the caller without further processing. */
|
|
/* It is up to the caller to strip off the trailing end of message tag */
|
|
/* \r\n.\r\n if one is appended to the message. Note the end of */
|
|
/* message is included in the packet length. */
|
|
/* */
|
|
/* When packets are received with only the end of message tag (EOM), */
|
|
/* this function returns zero bytes retrieved and sets final_packet to */
|
|
/* true. */
|
|
/* */
|
|
/* If the status return is NX_SUCCESS, the caller MUST release the */
|
|
/* packet, even if there bytes_retrieved is set to zero. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* recv_packet_ptr Pointer to received packet */
|
|
/* bytes_retrieved Received packet length */
|
|
/* final_packet If last packet of message */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* None */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_mail_item_message_get(NX_POP3_CLIENT *client_ptr, NX_PACKET **recv_packet_ptr, ULONG *bytes_retrieved, UINT *final_packet)
|
|
{
|
|
UINT status;
|
|
UINT index;
|
|
CHAR *buffer_ptr;
|
|
|
|
/* Initialize results to no data retrieved, or if the received packet is the last in the message. */
|
|
*final_packet = NX_FALSE;
|
|
*bytes_retrieved = 0;
|
|
|
|
/* Verify client is ready to download mail messages. */
|
|
if (client_ptr -> nx_pop3_client_ready_to_download == NX_FALSE)
|
|
{
|
|
|
|
return NX_POP3_CLIENT_INVALID_STATE;
|
|
}
|
|
|
|
if (client_ptr -> nx_pop3_client_message_ptr)
|
|
{
|
|
status = NX_SUCCESS;
|
|
*recv_packet_ptr = client_ptr -> nx_pop3_client_message_ptr;
|
|
client_ptr -> nx_pop3_client_message_ptr = NX_NULL;
|
|
}
|
|
else
|
|
{
|
|
|
|
/* Retrieve the next data packet. */
|
|
status = nx_tcp_socket_receive(&client_ptr -> nx_pop3_client_tcp_socket, recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
}
|
|
|
|
if (status == NX_SUCCESS)
|
|
{
|
|
|
|
/* Update the bytes_retrieved with amount of data in the packet. */
|
|
*bytes_retrieved = (*recv_packet_ptr) -> nx_packet_length;
|
|
|
|
/* Check for end of message tag in this packet. */
|
|
if (*bytes_retrieved > (sizeof(NX_POP3_END_OF_MESSAGE) - 1))
|
|
{
|
|
buffer_ptr = (CHAR *)(*recv_packet_ptr) -> nx_packet_prepend_ptr;
|
|
|
|
index = *bytes_retrieved - (sizeof(NX_POP3_END_OF_MESSAGE) - 1);
|
|
|
|
/* Determine if the end of the data contains the terminating \r\n.\r\n marker. */
|
|
if (memcmp((buffer_ptr + index), NX_POP3_END_OF_MESSAGE, (sizeof(NX_POP3_END_OF_MESSAGE) - 1)) == 0)
|
|
{
|
|
|
|
/* It does; indicate this is the end of the mail download. */
|
|
*final_packet = NX_TRUE;
|
|
|
|
/* Client cannot download any data for this particular mail item. */
|
|
client_ptr -> nx_pop3_client_ready_to_download = NX_FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
if (
|
|
(memcmp((*recv_packet_ptr) -> nx_packet_prepend_ptr, NX_POP3_END_OF_MESSAGE, (sizeof(NX_POP3_END_OF_MESSAGE) - 1))== 0) ||
|
|
(memcmp((*recv_packet_ptr) -> nx_packet_prepend_ptr, NX_POP3_END_OF_MESSAGE_TAG, (sizeof(NX_POP3_END_OF_MESSAGE_TAG) - 1))== 0)
|
|
)
|
|
{
|
|
|
|
/* Yes, but this is not considered part of the message. Indicate this with the bytes retrieved. */
|
|
*bytes_retrieved = 0;
|
|
|
|
/* It does; indicate this is the end of the mail download. */
|
|
*final_packet = NX_TRUE;
|
|
|
|
/* Client cannot download any data for this particular mail item. */
|
|
client_ptr -> nx_pop3_client_ready_to_download = NX_FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nxe_pop3_client_mail_item_delete PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function performs error checking for the delete mail item */
|
|
/* service. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* mail_index Index of mail item to delete */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nx_pop3_client_mail_item_delete Actual delete mail service */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nxe_pop3_client_mail_item_delete(NX_POP3_CLIENT *client_ptr, UINT mail_index)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
|
|
/* Check for invalid pointer input. */
|
|
if (client_ptr == NX_NULL)
|
|
{
|
|
return NX_PTR_ERROR;
|
|
}
|
|
|
|
/* Check for invalid mail item input. */
|
|
if (mail_index == 0)
|
|
{
|
|
|
|
return NX_POP3_CLIENT_INVALID_INDEX;
|
|
}
|
|
|
|
status = _nx_pop3_client_mail_item_delete(client_ptr, mail_index);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_mail_item_delete PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function sends the DELE command for the specified mail item */
|
|
/* and verifies the server will delete the item. Note that for some */
|
|
/* servers, items marked for deletion are not deleted immediately, in */
|
|
/* some cases only if they receive the QUIT command. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* mail_item Index into POP3 mailbox */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_PTR_ERROR Invalid pointer parameter */
|
|
/* NX_POP3_INVALID_MAIL_ITEM Invalid mail index input */
|
|
/* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
|
|
/* Packet too small for command */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* nx_packet_allocate Allocate packet from packet pool */
|
|
/* nx_packet_release Release packet back to pool */
|
|
/* nx_tcp_socket_send Send packet out TCP socket */
|
|
/* nx_tcp_socket_receive Retrieve packet from TCP socket */
|
|
/* _nx_pop3_parse_response Extract word from server response */
|
|
/* _nx_pop3_server_number_convert Convert integer to ascii */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application Code */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
|
|
/* verified memcpy use cases, */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_mail_item_delete(NX_POP3_CLIENT *client_ptr, UINT mail_index)
|
|
{
|
|
|
|
UINT status;
|
|
UINT size;
|
|
NX_PACKET *packet_ptr, *recv_packet_ptr;
|
|
CHAR *buffer_ptr;
|
|
CHAR argument[10];
|
|
UINT packet_type;
|
|
|
|
|
|
/* Allocate a packet. */
|
|
packet_type = NX_TCP_PACKET;
|
|
|
|
/* Allocate a packet. */
|
|
status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
|
|
&packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
buffer_ptr = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
|
|
|
|
/* Convert the ascii word to a number. */
|
|
size = _nx_pop3_server_number_convert(mail_index, &argument[0]);
|
|
|
|
/* Check packet payload is large enough for DEL request. */
|
|
if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_DELE) - 1) + 1 + size +
|
|
(sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= packet_ptr -> nx_packet_data_end)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
/* Send the DELE command. */
|
|
memcpy(buffer_ptr, NX_POP3_COMMAND_DELE, (sizeof(NX_POP3_COMMAND_DELE) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_DELE) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_DELE) - 1);
|
|
buffer_ptr += (sizeof(NX_POP3_COMMAND_DELE) - 1);
|
|
|
|
|
|
memcpy(buffer_ptr, " ", 1); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length++;
|
|
packet_ptr -> nx_packet_append_ptr++;
|
|
buffer_ptr++;
|
|
|
|
memcpy(buffer_ptr, &argument[0], size); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += size;
|
|
packet_ptr -> nx_packet_append_ptr += size;
|
|
buffer_ptr += size;
|
|
|
|
memcpy(buffer_ptr, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
buffer_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
|
|
/* Send the DELE command out. */
|
|
status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Receive server reply to DELE command. */
|
|
status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error condition. */
|
|
return(status);
|
|
}
|
|
|
|
if (recv_packet_ptr -> nx_packet_next)
|
|
{
|
|
|
|
/* Chained packet is not supported. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
return(NX_INVALID_PACKET);
|
|
}
|
|
|
|
/* Set a pointer to the packet data. */
|
|
buffer_ptr = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Parse the first argument of the server reply. */
|
|
_nx_pop3_parse_response(buffer_ptr, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Initialize status to server error status received. */
|
|
status = NX_POP3_SERVER_ERROR_STATUS;
|
|
|
|
/* Did the server accept the Client command? */
|
|
if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
|
|
{
|
|
|
|
/* Yes, set status to successful completion. */
|
|
status = NX_SUCCESS;
|
|
}
|
|
|
|
nx_packet_release(recv_packet_ptr);
|
|
|
|
return status;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nxe_pop3_client_quit PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* The service performs error checking for the send QUIT service. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to POP3 Client */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_SUCCESS Successful completion status */
|
|
/* NX_PTR_ERROR Invalid pointer input */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application thread */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nx_pop3_client_quit Actual send QUIT command service */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nxe_pop3_client_quit(NX_POP3_CLIENT *client_ptr)
|
|
{
|
|
|
|
UINT status;
|
|
|
|
if (client_ptr == NX_NULL)
|
|
{
|
|
return NX_PTR_ERROR;
|
|
}
|
|
|
|
status = _nx_pop3_client_quit(client_ptr);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_quit PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* The service sends a QUIT command to the Client POP3 server. The */
|
|
/* QUIT command takes no arguments and can be called at any time during*/
|
|
/* the Client session. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to POP3 Client */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_SUCCESS Successful completion status */
|
|
/* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
|
|
/* Packet too small for command */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* Application thread */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* None */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
|
|
/* verified memcpy use cases, */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_quit(NX_POP3_CLIENT *client_ptr)
|
|
{
|
|
|
|
UINT status;
|
|
NX_PACKET *packet_ptr, *recv_packet_ptr;
|
|
CHAR *buffer_ptr;
|
|
CHAR argument[10];
|
|
UINT packet_type;
|
|
|
|
|
|
packet_type = NX_TCP_PACKET;
|
|
|
|
/* Allocate a packet. */
|
|
status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
|
|
&packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
buffer_ptr = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
|
|
|
|
/* Check packet payload will hold the QUIT request. */
|
|
if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_QUIT) - 1) + 1 +
|
|
(sizeof(NX_POP3_COMMAND_TERMINATION) - 1)) >= packet_ptr -> nx_packet_data_end)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
memcpy(buffer_ptr, NX_POP3_COMMAND_QUIT, (sizeof(NX_POP3_COMMAND_QUIT) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_QUIT) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_QUIT) - 1);
|
|
buffer_ptr += (sizeof(NX_POP3_COMMAND_QUIT) - 1);
|
|
|
|
memcpy(buffer_ptr, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
buffer_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
|
|
/* Send the packet out. */
|
|
status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Receive server reply over session socket. */
|
|
status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error condition. */
|
|
return(status);
|
|
}
|
|
|
|
if (recv_packet_ptr -> nx_packet_next)
|
|
{
|
|
|
|
/* Chained packet is not supported. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
return(NX_INVALID_PACKET);
|
|
}
|
|
|
|
/* Set a pointer to the packet data. */
|
|
buffer_ptr = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Parse the first argument of the server reply. */
|
|
_nx_pop3_parse_response(buffer_ptr, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Initialize status to bad reply error condition. */
|
|
status = NX_POP3_SERVER_ERROR_STATUS;
|
|
|
|
/* Did the server accept the Client command? */
|
|
if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
|
|
{
|
|
|
|
/* Yes, set status to successful completion. */
|
|
status = NX_SUCCESS;
|
|
}
|
|
|
|
nx_packet_release(recv_packet_ptr);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_digest_authenticate PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function creates an MD5 digest based on input string which per */
|
|
/* POP3 protocol is the process ID and secret (e.g. Client password). */
|
|
/* This digest is used in APOP commands for the Client to authenticate */
|
|
/* itself without clear texting it's password. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr POP3 Client pointer */
|
|
/* process_ID_ptr Pointer to process_ID string */
|
|
/* process_ID_length Process ID string length */
|
|
/* result Pointer to MD5 digest */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_SUCCESS Successful completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nx_md5_initialize Initialize MD5 algorithm */
|
|
/* _nx_md5_update Update MD5 digest */
|
|
/* _nx_md5_digest_calculate Complete the MD5 algorithm */
|
|
/* _nx_pop3_hex_ascii_convert Convert digest to ascii */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* _nx_pop3_client_apop Send APOP cmd to Server */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_digest_authenticate(NX_POP3_CLIENT *client_ptr, CHAR *process_ID_ptr, UINT process_ID_length, CHAR *result)
|
|
{
|
|
|
|
CHAR md5_binary[NX_POP3_MAX_BINARY_MD5];
|
|
|
|
/* Initialize the Client session MD5 data. */
|
|
_nx_md5_initialize(&client_ptr -> nx_pop3_client_md5data);
|
|
|
|
|
|
_nx_md5_update(&client_ptr -> nx_pop3_client_md5data, (unsigned char *)process_ID_ptr, process_ID_length);
|
|
|
|
/* Finish calculation of the MD5 digest. */
|
|
_nx_md5_digest_calculate(&client_ptr -> nx_pop3_client_md5data, (unsigned char *)&md5_binary[0]);
|
|
|
|
/* Convert digest to ASCII Hex representation. */
|
|
_nx_pop3_hex_ascii_convert(&md5_binary[0], NX_POP3_MAX_BINARY_MD5, result);
|
|
|
|
/* Return successful completion */
|
|
return NX_SUCCESS;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_parse_process_id PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function extracts the process ID in the greeting from server. */
|
|
/* If found the Server is indicating we may use APOP to secure (open) */
|
|
/* the mailbox. The process ID is saved to the POP3 Client instance. If*/
|
|
/* no process ID is found, this field is set to NULL. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to Client */
|
|
/* buffer Pointer to server reply buffer */
|
|
/* buffer_length Size of server reply buffer */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* _nx_pop3_client_connect Connect and authenticate with server*/
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* None */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
VOID _nx_pop3_parse_process_id(NX_POP3_CLIENT *client_ptr, CHAR *buffer, UINT buffer_length)
|
|
{
|
|
|
|
CHAR c;
|
|
UINT index;
|
|
UINT pid_index;
|
|
|
|
|
|
/* Set a pointer to the start of the buffer to search. */
|
|
index = 0;
|
|
|
|
/* Clear memory for parsing the server process ID. */
|
|
memset(&client_ptr -> nx_pop3_server_process_id[0], 0, NX_POP3_SERVER_PROCESS_ID_SIZE);
|
|
|
|
while(index < buffer_length)
|
|
{
|
|
c = *buffer;
|
|
if (c == '<')
|
|
{
|
|
|
|
/* Found the start of the process ID. Now save it to the session instance including the angle brackets. */
|
|
pid_index = 0;
|
|
|
|
/* Check that we don't go over the size of the process ID buffer or off the end of the packet data. */
|
|
while ((pid_index < NX_POP3_SERVER_PROCESS_ID_SIZE) && (index < buffer_length))
|
|
{
|
|
|
|
/* Copy the next character and advance the counters and buffer pointer. */
|
|
client_ptr -> nx_pop3_server_process_id[pid_index] = *buffer;
|
|
|
|
/* Check if this is the end of the time stamp which is included in the process id string. . */
|
|
if (*buffer == '>')
|
|
{
|
|
|
|
/* This is the enclosing bracket. We're done. */
|
|
return;
|
|
}
|
|
|
|
index++;
|
|
pid_index++;
|
|
buffer++;
|
|
}
|
|
|
|
}
|
|
index++;
|
|
buffer++;
|
|
}
|
|
|
|
/* If we got here, we did not find any process IDs. */
|
|
return;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_parse_response PORTABLE C */
|
|
/* 6.1.4 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This service parses the specified argument from the input buffer */
|
|
/* and returns a pointer to the argument if found, else the a NULL */
|
|
/* pointer. Dashes are handled as word separators. */
|
|
/* */
|
|
/* crlf_are_word_breaks indicates if CR LF's should be handled as word */
|
|
/* separators. convert_to_uppercase indicates if the argument should be*/
|
|
/* converted to uppercase. */
|
|
/* */
|
|
/* This service removes CR LF's at the end of the message. It does not*/
|
|
/* allocate or clear argument memory, but does. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* buffer Pointer to buffer to parse */
|
|
/* argument_index Index of argument to parse */
|
|
/* buffer_length Buffer size */
|
|
/* argument Pointer to argument parsed */
|
|
/* argument_length Argument buffer size */
|
|
/* convert_to_uppercase Convert argument to uppercase */
|
|
/* crlf_are_word_breaks Handle CR LF's as word breaks */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* None */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* None */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */
|
|
/* buffer length verification, */
|
|
/* resulting in version 6.1.4 */
|
|
/* */
|
|
/**************************************************************************/
|
|
void _nx_pop3_parse_response(CHAR *buffer, UINT argument_index, UINT buffer_length, CHAR *argument, UINT argument_length,
|
|
UINT convert_to_uppercase, UINT crlf_are_word_breaks)
|
|
{
|
|
|
|
UINT i = 0;
|
|
UINT j = 0;
|
|
UINT argument_char_count;
|
|
|
|
|
|
/* Check for invalid input. */
|
|
if ((buffer == NX_NULL)|| (buffer[0] == 0x0) || (argument == NX_NULL) || (buffer_length == 0) ||
|
|
(argument_length == 0) || (argument_index == 0))
|
|
{
|
|
|
|
/* Return with argument not found status. */
|
|
return;
|
|
}
|
|
|
|
/* Initialize the argument to not found with NULL character. */
|
|
*argument = (CHAR)0x0;
|
|
argument_char_count = 0;
|
|
|
|
/* Is this the first argument? */
|
|
if (argument_index == 1)
|
|
{
|
|
|
|
/* Yes, search each character up to the end of the buffer for the first separator. */
|
|
while (i < buffer_length)
|
|
{
|
|
|
|
/* Did we find it? */
|
|
if (*buffer == ' ')
|
|
{
|
|
|
|
/* Yes, we're done with this loop! */
|
|
break;
|
|
}
|
|
|
|
/* Treat a hyphen as word breaks if it is between words, not if it is the first char. */
|
|
if (*buffer == '-' && i > 0)
|
|
{
|
|
|
|
/* Yes, we're done with this loop! */
|
|
break;
|
|
}
|
|
|
|
/* Did we go past the argument size limit? */
|
|
if (argument_char_count >= argument_length)
|
|
{
|
|
|
|
/* Yes, no argument found. */
|
|
break;
|
|
}
|
|
|
|
/* Copy the next character into the argument, converting
|
|
to uppercase if the caller requested this. */
|
|
*argument++ = convert_to_uppercase ? (CHAR)toupper((INT)(*buffer)) : *buffer;
|
|
|
|
argument_char_count++;
|
|
|
|
/* Move to the next character. */
|
|
i++;
|
|
buffer++;
|
|
}
|
|
|
|
/* Are we at the end of the buffer? */
|
|
if ((i == buffer_length) && (buffer_length >= 2))
|
|
{
|
|
|
|
/* Yes, is there a line terminator? */
|
|
if (*(argument - 2) == 0x0D && *(argument - 1) == 0x0A)
|
|
{
|
|
|
|
/* Yes, remove it with a null character */
|
|
*(argument - 2) = (CHAR) 0x0;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* No, we're not parsing the first argument. */
|
|
|
|
/* Mark the start of the argument at the separator after the end of the previous argument. */
|
|
while (j < argument_index && i < buffer_length)
|
|
{
|
|
|
|
/* Keep track of the number of separators in the buffer */
|
|
|
|
/* Did we hit a line terminator? */
|
|
if ((*buffer == 0x0D) && (*(buffer + 1) == 0x0A))
|
|
{
|
|
|
|
/* Yes, Update the count of separators. */
|
|
j++;
|
|
|
|
/* Are line terminators as word breaks? */
|
|
if (!crlf_are_word_breaks)
|
|
{
|
|
|
|
/* No, treat as the end of the search string buffer. */
|
|
break;
|
|
}
|
|
|
|
buffer++;
|
|
}
|
|
|
|
/* Did we hit a space or a dash in the first argument? */
|
|
else if (*buffer == ' ' ||
|
|
(*buffer == '-' && j == 0))
|
|
{
|
|
|
|
/* These are counted as separators (note that
|
|
dashes found in arguments after the first arg
|
|
are NOT considered separators */
|
|
j++;
|
|
}
|
|
else
|
|
{
|
|
|
|
if (j == argument_index - 1)
|
|
{
|
|
|
|
/* Have we exceeded the limit on the argument size? */
|
|
if (argument_char_count < argument_length)
|
|
{
|
|
|
|
/* No, copy the next character into the argument. */
|
|
argument_char_count++;
|
|
|
|
/* Convert to uppercase if the caller requests. */
|
|
*argument++ = convert_to_uppercase ? (CHAR)toupper((INT)*buffer) : *buffer;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Get the next character */
|
|
i++;
|
|
buffer++;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_hex_ascii_convert PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function converts hexadecimal characters into an ASCII string. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* source Source hex string */
|
|
/* source_length Length of source string */
|
|
/* destination Pointer to destination string */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* None */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* None */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* _nx_pop3_utility_digest_authenticate Create digest for */
|
|
/* authentication */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
VOID _nx_pop3_hex_ascii_convert(CHAR *source, UINT source_length, CHAR *destination)
|
|
{
|
|
|
|
UINT i,j;
|
|
CHAR digit;
|
|
|
|
|
|
/* Setup destination index. */
|
|
j = 0;
|
|
|
|
/* Loop to process the entire source string. */
|
|
for (i = 0; i < source_length; i++)
|
|
{
|
|
|
|
/* Pickup the first nibble. */
|
|
digit = (source[i] >> 4) & 0xF;
|
|
|
|
/* Convert to ASCII and store. */
|
|
if (digit <= 9)
|
|
destination[j++] = (CHAR)(digit + '0');
|
|
else
|
|
destination[j++] = (CHAR)(digit + 'a' - 10);
|
|
|
|
/* Pickup the second nibble. */
|
|
digit = source[i] & 0xF;
|
|
|
|
/* Convert to ASCII and store. */
|
|
if (digit <= 9)
|
|
destination[j++] = (CHAR)(digit + '0');
|
|
else
|
|
destination[j++] = (CHAR)(digit + 'a' - 10);
|
|
}
|
|
|
|
/* Place a NULL in the destination string. */
|
|
destination[j] = (CHAR) NX_NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_server_number_convert PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function converts a number into an ASCII string and returns the*/
|
|
/* size of the string holding the number. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* number Unsigned integer number */
|
|
/* string_to_convert Destination string */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* Size Number of bytes in string */
|
|
/* (0 implies an error) */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* _nx_pop3_client_mail_item_get Get mail item size */
|
|
/* _nx_pop3_client_mail_item_delete Delete mail item */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_server_number_convert(UINT number, CHAR *string_to_convert)
|
|
{
|
|
|
|
UINT j;
|
|
UINT digit;
|
|
UINT size;
|
|
|
|
|
|
/* Initialize counters. */
|
|
size = 0;
|
|
|
|
/* Loop to convert the number to ASCII. */
|
|
while (size < 9)
|
|
{
|
|
|
|
/* Shift the current digits over one. */
|
|
for (j = size; j != 0; j--)
|
|
{
|
|
|
|
/* Move each digit over one place. */
|
|
string_to_convert[j] = string_to_convert[j - 1];
|
|
}
|
|
|
|
/* Compute the next decimal digit. */
|
|
digit = number % 10;
|
|
|
|
/* Update the input number. */
|
|
number = number / 10;
|
|
|
|
/* Store the new digit in ASCII form. */
|
|
string_to_convert[0] = (CHAR) (digit + 0x30);
|
|
|
|
/* Increment the size. */
|
|
size++;
|
|
|
|
/* Determine if the number is now zero. */
|
|
if (number == 0)
|
|
break;
|
|
}
|
|
|
|
/* Make the string NULL terminated. */
|
|
string_to_convert[size] = (CHAR) NX_NULL;
|
|
|
|
/* Determine if there is an overflow error. */
|
|
if (number)
|
|
{
|
|
|
|
/* Error, return bad values to user. */
|
|
size = 0;
|
|
string_to_convert[0] = '0';
|
|
}
|
|
|
|
/* Return size to caller. */
|
|
return(size);
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_connect PORTABLE C */
|
|
/* 6.1.6 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function binds the Client socket to the POP3 port and connects */
|
|
/* to the POP3 server. If the connection is made, this function */
|
|
/* processes the server greeting, and initiates the APOP/USER */
|
|
/* authentication with the sever. */
|
|
/* */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* server_ip_address Pointer to POP3 server IP address */
|
|
/* server_port POP3 server port */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_SUCCESS Successful completion status */
|
|
/* NX_POP3_PARAM_ERROR Invalid Client user or password */
|
|
/* NX_POP3_CANNOT_PARSE_REPLY Unable to parse server reply */
|
|
/* status TCP service completion status */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* _nx_pop3_client_create Create POP3 Client and socket */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* nx_tcp_client_socket_bind NetX TCP socket bind service */
|
|
/* nx_tcp_client_socket_connect NetX TCP socket connect service */
|
|
/* nx_tcp_socket_receive NetX TCP socket receive service */
|
|
/* _nx_pop3_parse_response Parse Server reply code */
|
|
/* _nx_pop3_parse_process_id Parse server ID for APOP digest */
|
|
/* _nx_pop3_client_apop Send Authenticated user/pass */
|
|
/* _nx_pop3_client_user_pass Send User Pass in clear text */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), */
|
|
/* resulting in version 6.1 */
|
|
/* 04-02-2021 Yuxin Zhou Modified comment(s), and */
|
|
/* corrected the client port, */
|
|
/* resulting in version 6.1.6 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_connect(NX_POP3_CLIENT *client_ptr, ULONG server_ip_address, ULONG server_port)
|
|
{
|
|
|
|
UINT status;
|
|
NX_PACKET *recv_packet_ptr;
|
|
CHAR *buffer_ptr;
|
|
CHAR argument[10];
|
|
|
|
|
|
/* Check for client name/password/shared secret too long for allotted buffer. */
|
|
if ((_nx_utility_string_length_check(&client_ptr -> nx_pop3_client_name[0], NX_NULL, NX_POP3_MAX_USERNAME)) ||
|
|
(_nx_utility_string_length_check(&client_ptr -> nx_pop3_client_password[0], NX_NULL, NX_POP3_MAX_PASSWORD)))
|
|
{
|
|
|
|
return NX_POP3_PARAM_ERROR;
|
|
}
|
|
|
|
status = nx_tcp_client_socket_bind(&client_ptr -> nx_pop3_client_tcp_socket, NX_ANY_PORT, NX_IP_PERIODIC_RATE);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
status = nx_tcp_client_socket_connect(&client_ptr -> nx_pop3_client_tcp_socket,
|
|
server_ip_address,
|
|
server_port,
|
|
NX_POP3_CLIENT_CONNECTION_TIMEOUT);
|
|
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* Receive server reply over session socket. */
|
|
status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error condition. */
|
|
return(status);
|
|
}
|
|
|
|
if (recv_packet_ptr -> nx_packet_next)
|
|
{
|
|
|
|
/* Chained packet is not supported. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
return(NX_INVALID_PACKET);
|
|
}
|
|
|
|
/* Set a pointer to the packet data. */
|
|
buffer_ptr = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Parse the first argument of the server reply. */
|
|
_nx_pop3_parse_response(buffer_ptr, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Initialize status to bad reply error condition. */
|
|
status = NX_POP3_SERVER_ERROR_STATUS;
|
|
|
|
/* Did the server accept the Client command? */
|
|
if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
|
|
{
|
|
|
|
if (client_ptr -> nx_pop3_client_enable_APOP_authentication)
|
|
{
|
|
|
|
/* Attempt to extract the server process ID in the greeting. */
|
|
_nx_pop3_parse_process_id(client_ptr, buffer_ptr, recv_packet_ptr -> nx_packet_length);
|
|
|
|
/* Did we find a process ID? */
|
|
if (client_ptr -> nx_pop3_server_process_id[0] != 0)
|
|
{
|
|
|
|
/* Do APOP authentication. */
|
|
status = _nx_pop3_client_apop(client_ptr);
|
|
|
|
if (status == NX_SUCCESS)
|
|
{
|
|
return status;
|
|
}
|
|
else if (status != NX_POP3_SERVER_ERROR_STATUS)
|
|
{
|
|
|
|
/* Another error encountered (packet pool depletion, broken connection, etc*/
|
|
return status;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Possibly the server doesn't like APOP. Try User Pass */
|
|
client_ptr -> nx_pop3_client_enable_APOP_authentication = NX_FALSE;
|
|
}
|
|
}
|
|
|
|
/* Try USER PASS authentication. */
|
|
status = _nx_pop3_client_user_pass(client_ptr);
|
|
}
|
|
|
|
nx_packet_release(recv_packet_ptr);
|
|
|
|
return status;
|
|
}
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_apop PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function attempts to authenticate the POP3 client with the POP3*/
|
|
/* server. If successful returns NX_SUCCESS. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_SUCCESS Authentication accepted by server */
|
|
/* NX_POP3_APOP_FAILED_MD5_DIGEST Error creating digest */
|
|
/* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
|
|
/* Packet too small for command */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* nx_packet_allocate Allocate packet from packet pool */
|
|
/* nx_packet_release Release packet back to pool */
|
|
/* nx_tcp_socket_send Send packet out TCP socket */
|
|
/* nx_tcp_socket_receive Retrieve packet from TCP socket */
|
|
/* _nx_pop3_parse_response Extract word from server response */
|
|
/* _nx_pop3_digest_authenticate Create authentication string */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* nx_pop3_client_connect Connect with POP3 server */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
|
|
/* verified memcpy use cases, */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_apop(NX_POP3_CLIENT *client_ptr)
|
|
{
|
|
|
|
UINT status;
|
|
NX_PACKET *packet_ptr, *recv_packet_ptr;
|
|
CHAR *buffer;
|
|
CHAR argument[10];
|
|
CHAR md5_digest_buffer[NX_POP3_MAX_ASCII_MD5 + 1];
|
|
UINT packet_type;
|
|
UINT index;
|
|
CHAR userid_buffer[100];
|
|
UINT server_process_id_length;
|
|
UINT client_password_length;
|
|
UINT client_name_length;
|
|
UINT md5_digest_buffer_length;
|
|
|
|
|
|
packet_type = NX_TCP_PACKET;
|
|
|
|
/* Allocate a packet. */
|
|
status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
|
|
&packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Create the APOP digest. */
|
|
memset(&userid_buffer[0],0,sizeof(userid_buffer));
|
|
|
|
/* Validate copy size. */
|
|
if (_nx_utility_string_length_check(client_ptr -> nx_pop3_server_process_id, &server_process_id_length, NX_POP3_SERVER_PROCESS_ID_SIZE) ||
|
|
_nx_utility_string_length_check(client_ptr -> nx_pop3_client_password, &client_password_length, NX_POP3_MAX_PASSWORD))
|
|
{
|
|
nx_packet_release(packet_ptr);
|
|
return(NX_POP3_INSUFFICIENT_PACKET_PAYLOAD);
|
|
}
|
|
if((server_process_id_length + client_password_length) > sizeof(userid_buffer))
|
|
{
|
|
nx_packet_release(packet_ptr);
|
|
return(NX_POP3_INSUFFICIENT_PACKET_PAYLOAD);
|
|
}
|
|
|
|
memcpy(&userid_buffer[0], &client_ptr -> nx_pop3_server_process_id[0], server_process_id_length); /* Use case of memcpy is verified. */
|
|
index = server_process_id_length;
|
|
memcpy(&userid_buffer[index], &client_ptr -> nx_pop3_client_password[0], client_password_length); /* Use case of memcpy is verified. */
|
|
status = _nx_pop3_digest_authenticate(client_ptr, &userid_buffer[0], (server_process_id_length + client_password_length), &md5_digest_buffer[0]);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
nx_packet_release(packet_ptr);
|
|
|
|
/* Return failed APOP attempt error condition. */
|
|
return NX_POP3_APOP_FAILED_MD5_DIGEST;
|
|
}
|
|
|
|
/* Verify the packet payload will hold the APOP command. */
|
|
if (_nx_utility_string_length_check(client_ptr -> nx_pop3_client_name, &client_name_length, NX_POP3_MAX_USERNAME) ||
|
|
_nx_utility_string_length_check(md5_digest_buffer, &md5_digest_buffer_length, NX_POP3_MAX_ASCII_MD5))
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_APOP) - 1)
|
|
+ (sizeof(NX_POP3_COMMAND_TERMINATION) - 1) + 2
|
|
+ client_name_length
|
|
+ md5_digest_buffer_length) >= packet_ptr -> nx_packet_data_end)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
buffer = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
|
|
|
|
/* Create the APOP command. */
|
|
memcpy(buffer, NX_POP3_COMMAND_APOP, (sizeof(NX_POP3_COMMAND_APOP) - 1)); /* Use case of memcpy is verified. */
|
|
buffer += (sizeof(NX_POP3_COMMAND_APOP) - 1);
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_APOP) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_APOP) - 1);
|
|
|
|
memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
|
|
buffer++;
|
|
packet_ptr -> nx_packet_append_ptr++;
|
|
packet_ptr -> nx_packet_length++;
|
|
|
|
memcpy(buffer, client_ptr -> nx_pop3_client_name, client_name_length); /* Use case of memcpy is verified. */
|
|
buffer += client_name_length;
|
|
packet_ptr -> nx_packet_length += client_name_length;
|
|
packet_ptr -> nx_packet_append_ptr += client_name_length;
|
|
|
|
memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
|
|
buffer++;
|
|
packet_ptr -> nx_packet_append_ptr++;
|
|
packet_ptr -> nx_packet_length++;
|
|
|
|
memcpy(buffer, &md5_digest_buffer[0], md5_digest_buffer_length); /* Use case of memcpy is verified. */
|
|
buffer += md5_digest_buffer_length;
|
|
packet_ptr -> nx_packet_length += md5_digest_buffer_length;
|
|
packet_ptr -> nx_packet_append_ptr += md5_digest_buffer_length;
|
|
|
|
memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
|
|
/* Send the packet out. */
|
|
status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Receive server reply over session socket. */
|
|
status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error condition. */
|
|
return(status);
|
|
}
|
|
|
|
if (recv_packet_ptr -> nx_packet_next)
|
|
{
|
|
|
|
/* Chained packet is not supported. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
return(NX_INVALID_PACKET);
|
|
}
|
|
|
|
/* Set a pointer to the packet data. */
|
|
buffer = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Parse the first argument of the server reply. */
|
|
_nx_pop3_parse_response(buffer, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Initialize status to bad reply error condition. */
|
|
status = NX_POP3_SERVER_ERROR_STATUS;
|
|
|
|
/* Did the server accept the Client command? */
|
|
if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
|
|
{
|
|
|
|
/* APOP command accepted. */
|
|
status = NX_SUCCESS;
|
|
}
|
|
|
|
nx_packet_release(recv_packet_ptr);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/**************************************************************************/
|
|
/* */
|
|
/* FUNCTION RELEASE */
|
|
/* */
|
|
/* _nx_pop3_client_user_pass PORTABLE C */
|
|
/* 6.1 */
|
|
/* AUTHOR */
|
|
/* */
|
|
/* Yuxin Zhou, Microsoft Corporation */
|
|
/* */
|
|
/* DESCRIPTION */
|
|
/* */
|
|
/* This function attempts to login using client sername and password */
|
|
/* with the POP3 server. If successful returns NX_SUCCESS. */
|
|
/* */
|
|
/* INPUT */
|
|
/* */
|
|
/* client_ptr Pointer to client struct */
|
|
/* */
|
|
/* OUTPUT */
|
|
/* */
|
|
/* NX_SUCCESS Login accepted by server */
|
|
/* NX_POP3_INSUFFICIENT_PACKET_PAYLOAD */
|
|
/* Packet too small for command */
|
|
/* status Actual completion status */
|
|
/* */
|
|
/* CALLS */
|
|
/* */
|
|
/* nx_packet_allocate Allocate packet from packet pool */
|
|
/* nx_packet_release Release packet back to pool */
|
|
/* nx_tcp_socket_send Send packet out TCP socket */
|
|
/* nx_tcp_socket_receive Retrieve packet from TCP socket */
|
|
/* _nx_pop3_parse_response Extract word from server response */
|
|
/* _nx_pop3_digest_authenticate Create authentication string */
|
|
/* */
|
|
/* CALLED BY */
|
|
/* */
|
|
/* nx_pop3_client_connect Connect with POP3 server */
|
|
/* */
|
|
/* RELEASE HISTORY */
|
|
/* */
|
|
/* DATE NAME DESCRIPTION */
|
|
/* */
|
|
/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */
|
|
/* 09-30-2020 Yuxin Zhou Modified comment(s), and */
|
|
/* verified memcpy use cases, */
|
|
/* resulting in version 6.1 */
|
|
/* */
|
|
/**************************************************************************/
|
|
UINT _nx_pop3_client_user_pass(NX_POP3_CLIENT *client_ptr)
|
|
{
|
|
|
|
UINT status;
|
|
NX_PACKET *packet_ptr, *recv_packet_ptr, *next_recv_packet_ptr;
|
|
CHAR *buffer;
|
|
CHAR argument[10];
|
|
UINT packet_type;
|
|
UINT client_name_length;
|
|
UINT client_password_length;
|
|
|
|
|
|
packet_type = NX_TCP_PACKET;
|
|
|
|
/* Allocate a packet. */
|
|
status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
|
|
&packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Verify the packet payload will hold the user command message. */
|
|
if (_nx_utility_string_length_check(client_ptr -> nx_pop3_client_name, &client_name_length, NX_POP3_MAX_USERNAME))
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_USER) - 1) +
|
|
1 + client_name_length + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1))
|
|
>= packet_ptr -> nx_packet_data_end)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
buffer = (CHAR *)(packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
|
|
memcpy(buffer, NX_POP3_COMMAND_USER, (sizeof(NX_POP3_COMMAND_USER) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length = (sizeof(NX_POP3_COMMAND_USER) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_USER) - 1);
|
|
buffer += (sizeof(NX_POP3_COMMAND_USER) - 1);
|
|
|
|
memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length++;
|
|
packet_ptr -> nx_packet_append_ptr++;
|
|
buffer++;
|
|
|
|
memcpy(buffer, client_ptr -> nx_pop3_client_name, client_name_length); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += client_name_length;
|
|
packet_ptr -> nx_packet_append_ptr += client_name_length;
|
|
buffer += client_name_length;
|
|
|
|
memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
buffer += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
|
|
/* Send the packet out. */
|
|
status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Receive server reply to Client username over session socket. */
|
|
status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error condition. */
|
|
return(status);
|
|
}
|
|
|
|
if (recv_packet_ptr -> nx_packet_next)
|
|
{
|
|
|
|
/* Chained packet is not supported. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
return(NX_INVALID_PACKET);
|
|
}
|
|
|
|
/* Set a pointer to the packet data. */
|
|
buffer = (CHAR *)(recv_packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Parse the first argument of the server reply. */
|
|
_nx_pop3_parse_response(buffer, 1, recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Initialize status to bad reply error condition. */
|
|
status = NX_POP3_SERVER_ERROR_STATUS;
|
|
|
|
/* Did the server accept the Client command? */
|
|
if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
|
|
{
|
|
|
|
/* We are done with this packet. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
|
|
packet_type = NX_TCP_PACKET;
|
|
|
|
/* Allocate another packet. */
|
|
status = nx_packet_allocate(client_ptr -> nx_pop3_client_packet_pool_ptr,
|
|
&packet_ptr, packet_type, NX_POP3_CLIENT_PACKET_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Verify the packet payload will hold the password request. */
|
|
if (_nx_utility_string_length_check(client_ptr -> nx_pop3_client_password, &client_password_length, NX_POP3_MAX_PASSWORD))
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
if ((packet_ptr -> nx_packet_prepend_ptr + (sizeof(NX_POP3_COMMAND_PASS) - 1) +
|
|
1 + client_password_length + (sizeof(NX_POP3_COMMAND_TERMINATION) - 1))
|
|
>= packet_ptr -> nx_packet_data_end)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
return NX_POP3_INSUFFICIENT_PACKET_PAYLOAD;
|
|
}
|
|
|
|
buffer = (CHAR *)packet_ptr -> nx_packet_prepend_ptr;
|
|
memcpy(buffer, NX_POP3_COMMAND_PASS, (sizeof(NX_POP3_COMMAND_PASS) - 1)); /* Use case of memcpy is verified. */
|
|
buffer += (sizeof(NX_POP3_COMMAND_PASS) - 1);
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_PASS) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_PASS) - 1);
|
|
|
|
memcpy(buffer, " ", 1); /* Use case of memcpy is verified. */
|
|
buffer++;
|
|
packet_ptr -> nx_packet_length++;
|
|
packet_ptr -> nx_packet_append_ptr++;
|
|
|
|
memcpy(buffer, client_ptr -> nx_pop3_client_password, client_password_length); /* Use case of memcpy is verified. */
|
|
buffer += client_password_length;
|
|
packet_ptr -> nx_packet_length += client_password_length;
|
|
packet_ptr -> nx_packet_append_ptr += client_password_length;
|
|
|
|
memcpy(buffer, NX_POP3_COMMAND_TERMINATION, (sizeof(NX_POP3_COMMAND_TERMINATION) - 1)); /* Use case of memcpy is verified. */
|
|
buffer += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
packet_ptr -> nx_packet_length += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
packet_ptr -> nx_packet_append_ptr += (sizeof(NX_POP3_COMMAND_TERMINATION) - 1);
|
|
|
|
/* Send the next Client message out. */
|
|
status = nx_tcp_socket_send(&client_ptr -> nx_pop3_client_tcp_socket, packet_ptr, NX_POP3_TCP_SOCKET_SEND_WAIT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Release the packet. */
|
|
nx_packet_release(packet_ptr);
|
|
|
|
/* Return the error condition. */
|
|
return(status);
|
|
}
|
|
|
|
/* Receive server reply to Client password over session socket. */
|
|
status = nx_tcp_socket_receive(&(client_ptr -> nx_pop3_client_tcp_socket), &next_recv_packet_ptr, NX_POP3_SERVER_REPLY_TIMEOUT);
|
|
|
|
/* Check for error. */
|
|
if (status != NX_SUCCESS)
|
|
{
|
|
|
|
/* Return error condition. */
|
|
return(status);
|
|
}
|
|
|
|
if (next_recv_packet_ptr -> nx_packet_next)
|
|
{
|
|
|
|
/* Chained packet is not supported. */
|
|
nx_packet_release(next_recv_packet_ptr);
|
|
return(NX_INVALID_PACKET);
|
|
}
|
|
|
|
/* Set a pointer to the packet data. */
|
|
buffer = (CHAR *)(next_recv_packet_ptr -> nx_packet_prepend_ptr);
|
|
|
|
/* Parse the first argument of the server reply. */
|
|
_nx_pop3_parse_response(buffer, 1, next_recv_packet_ptr -> nx_packet_length, (CHAR *)&argument, 10, NX_FALSE, NX_FALSE);
|
|
|
|
/* Did the server accept the Client command? */
|
|
if (memcmp(argument, NX_POP3_POSITIVE_STATUS, (sizeof(NX_POP3_POSITIVE_STATUS) - 1)) == 0x0)
|
|
{
|
|
|
|
status = NX_SUCCESS;
|
|
}
|
|
|
|
/* We are done with this packet. */
|
|
nx_packet_release(next_recv_packet_ptr);
|
|
}
|
|
else
|
|
{
|
|
|
|
/* Server rejected the Client message. */
|
|
nx_packet_release(recv_packet_ptr);
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|