1 /*
2  * Copyright (c) 2011 QUALCOMM Incorporated.  All rights reserved.
3  * The file license.txt specifies the terms for use, modification, or
4  * redistribution.
5  *
6  */
7 
8 /*
9  * Revisions:
10  *
11  *   10/13/00  [rcg]
12  *       - Fitted LGL's TLS changes.
13  *
14  *   05/23/00  [rcg]
15  *       - Fixed case where buffer passed to pop_msg without a format
16  *         string.
17  *       - EUIDL no longer includes extra newline for single message.
18  *
19  *   03/14/00  [rcg]
20  *       - Handle hidden messages in pop_euidl().
21  *       - Minor syntactical tweaks.
22  *
23  *   03/01/00  [rcg]
24  *       - Handle case of hidden first message.
25  *
26  *   12/03/99  [rcg]:
27  *       - 'UIDL x' sent an incorrect UID string if the UID contained
28  *          the '%' character, while 'UIDL' worked correctly.  This is
29  *          because 'UIDL x' sends the response using pop_msg, and used
30  *          the UID string as the format string.  Now it uses "%s" as
31  *          the format string, and the UID string as a parameter.
32  *
33  */
34 
35 #include "config.h"
36 
37 #include <sys/types.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <sys/file.h>
41 #include <sys/wait.h>
42 #include <ctype.h>
43 #include <string.h>
44 
45 #if HAVE_STRINGS_H
46 #  include <strings.h>
47 #endif
48 
49 #ifndef HAVE_INDEX
50 #  define index(s,c)             strchr(s,c)
51 #endif
52 
53 #include "popper.h"
54 
55 
56 /*
57  *  uidl:   POP UIDL function to list messages by message-ids
58  */
59 
60 int
pop_uidl(p)61 pop_uidl (p)
62 POP     *   p;
63 {
64     char                    buffer [ MAXLINELEN ];     /*  Read buffer */
65     char                   *nl;
66     MsgInfoList            *mp;         /*  Pointer to message info list */
67     int                     msg_id = 0;
68     int                     x;
69     int                     len    = 0;
70 
71     if ( p->parm_count == 1 ) {
72         len = p->pop_parmlen[1];
73 
74         /*
75          * Convert the parameter into an integer
76          */
77         msg_id = atoi ( p->pop_parm[1] );
78     }
79 
80     /*
81      * Is requested message out of range?
82      */
83     if ( len > 0 ) {
84         if ( msg_id == 0 )
85             return ( pop_msg ( p, POP_FAILURE, HERE,
86                                "Parameter must be a number between 1 and %d",
87                                p->msg_count ) );
88 
89         /*
90          * Get a pointer to the message in the message list
91          */
92         mp = msg_ptr ( p, msg_id );
93         if ( mp == NULL )
94             return ( pop_msg ( p, POP_FAILURE, HERE,
95                                "Message %d out of range.", msg_id ) );
96 
97         if ( mp->del_flag )
98             return ( pop_msg ( p, POP_FAILURE, HERE,
99                                "Message %d has been marked for deletion.",
100                                msg_id ) );
101 
102         sprintf ( buffer, "%d %s", msg_id, mp->uidl_str );
103         nl = index ( buffer, NEWLINE );
104         if ( nl != NULL )
105             *nl = 0;
106         return ( pop_msg ( p, POP_SUCCESS, HERE, "%s", buffer ) );
107     } /* msg number specified */
108     else { /* yes, we can do this */
109         pop_msg ( p, POP_SUCCESS, HERE, "uidl command accepted." );
110 
111         for ( x = 1; x <= p->msg_count; x++ )
112         {
113             /*
114              * Get a pointer to the message in the message list
115              */
116             mp = msg_ptr ( p, x );
117             if ( mp == NULL )
118                 continue;
119 
120             /*
121              * Is the message flagged for deletion?
122              */
123             if ( mp->del_flag )
124                 continue;
125 
126             sprintf ( buffer, "%d %s",
127                       mp->visible_num,
128                       mp->uidl_str );
129             pop_sendline ( p, buffer );
130         } /* for loop */
131 
132     /*
133      * "." signals the end of a multi-line transmission
134      */
135     POP_WRITE_LIT   ( p, ".\r\n" );
136     pop_write_flush ( p );
137     } /* do all messages */
138 
139     return ( POP_SUCCESS );
140 }
141 
142 /*
143  *  euidl:   POP EUIDL function to list messages by message-ids and adds
144  *           message size and From: header text as well.  This is to help
145  *           the Newton do some pre-filtering before downloading messages.
146  */
147 
148 char *
from_hdr(p,mp,buf,len)149 from_hdr ( p, mp, buf, len )
150      POP         *p;
151      MsgInfoList *mp;
152      char        *buf;
153      size_t       len;
154 {
155   char *cp;
156   char *nl;
157 
158     fseek ( p->drop, mp->offset, 0 );
159     while ( fgets ( buf, len, p->drop ) != NULL ) {
160       if ( buf[0] == '\n' )
161         break;    /* From header not found */
162       if ( !strncasecmp ( "From:", buf, 5 ) ) {
163         cp = index ( buf, ':' );
164         while ( *++cp && ( *cp == ' ' || *cp == '\t' ) );
165         nl = index ( cp, NEWLINE );
166         if ( nl != NULL )
167             *nl = 0;
168         return ( cp );
169       }
170     }
171     return ( "" );
172 }
173 
174 int
pop_euidl(p)175 pop_euidl (p)
176 POP     *   p;
177 {
178     char                    buffer [ MAXLINELEN ];     /*  Read buffer */
179     char                    fromln [ MAXLINELEN ];     /*  Holds 'From:' line */
180     char                   *nl;
181     MsgInfoList            *mp;            /*  Pointer to message info list */
182     int                     msg_id = 0;
183     int                     x;
184     int                     len    = 0;
185 
186     if ( p->parm_count == 1 ) {
187         len = p->pop_parmlen[1];
188 
189         /*
190          * Convert the parameter into an integer
191          */
192         msg_id = atoi ( p->pop_parm[1] );
193     }
194 
195     /*
196      * Is requested message out of range?
197      */
198     if ( len > 0 && msg_id == 0 ) {
199         return ( pop_msg ( p, POP_FAILURE, HERE,
200                            "Parameter must be a number (range 1 to %d)",
201                            p->visible_msg_count ) );
202     }
203 
204     if ( len > 0 && ( msg_id < 1 || msg_id > p->visible_msg_count ) ) {
205         return ( pop_msg ( p, POP_FAILURE, HERE,
206                            "Message out of range.  %d visible messages in mail drop.",
207                            p->visible_msg_count ) );
208     }
209 
210     if ( msg_id > 0 ) {
211         /*
212          * Get a pointer to the message in the message list
213          */
214         mp = msg_ptr ( p, msg_id );
215         if ( mp == NULL ) {
216             return ( pop_msg ( p, POP_FAILURE, HERE,
217                                "Message %d out of range", msg_id ) );
218         } /* bad msg */
219 
220         if ( mp->del_flag ) {
221             return ( pop_msg ( p, POP_FAILURE, HERE,
222                                "Message %d has been marked for deletion.",
223                                msg_id ) );
224         } /* deleted */
225       else {
226           /*
227            * We have a valid message.
228            */
229           sprintf ( buffer, "%d %s", msg_id, mp->uidl_str );
230           nl = index ( buffer, NEWLINE );
231           if ( nl != NULL )
232               *nl = 0;
233           return  ( pop_msg ( p, POP_SUCCESS, HERE, "%s %ld %.128s",
234                     buffer, mp->length,
235                     from_hdr ( p, mp, fromln, sizeof(fromln) ) ) );
236         } /* valid single message */
237     } /* single message */
238     else {
239         /*
240          * yes, we can do this
241          */
242         pop_msg ( p, POP_SUCCESS, HERE, "uidl command accepted." );
243 
244         for ( x = 1; x <= p->msg_count; x++ )
245         {
246             /*
247              * Get a pointer to the message in the message list
248              */
249             mp = msg_ptr ( p, x );
250             if ( mp == NULL )
251                 continue;
252 
253             /*
254              * Is the message flagged for deletion?
255              */
256             if ( mp->del_flag )
257                 continue;
258 
259             sprintf ( buffer, "%d %s", x, mp->uidl_str );
260             nl = index ( buffer, NEWLINE );
261             if ( nl != NULL )
262                 *nl = 0;
263             sprintf ( buffer, "%s %ld %.128s\n",
264                       buffer, mp->length,
265                       from_hdr ( p, mp, fromln, sizeof(fromln) ) );
266             pop_sendline ( p, buffer );
267         } /* for loop */
268     } /* all messages */
269 
270     /*
271      * "." signals the end of a multi-line transmission
272      */
273     pop_write_line  ( p, "." );
274     pop_write_flush ( p );
275 
276     return ( POP_SUCCESS );
277 }
278 
279