temporary commit while I update master
[alpine.git] / pith / maillist.c
blob6c2743a04dd5c6a5c585f990a682f17771bcb955
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: maillist.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2017 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
20 * * * * * * * * * RFC 2369 support routines * * * * * * * *
24 #include "../pith/headers.h"
25 #include "../pith/maillist.h"
26 #include "../pith/state.h"
27 #include "../pith/url.h"
31 * Internal prototypes
33 int rfc2369_parse(char *, RFC2369_S *);
36 * * NOTE * These have to remain in sync with the MLCMD_* macros
37 * in maillist.h. Sorry.
39 static RFC2369FIELD_S rfc2369_fields[] = {
40 {"List-Help",
41 "get information about the list and instructions on how to join",
42 "seek help"},
43 {"List-Unsubscribe",
44 "remove yourself from the list (Unsubscribe)",
45 "UNsubscribe"},
46 {"List-Subscribe",
47 "add yourself to the list (Subscribe)",
48 "Subscribe"},
49 {"List-Post",
50 "send a message to the entire list (Post)",
51 "post a message"},
52 {"List-Owner",
53 "send a message to the list owner",
54 "contact the list owner"},
55 {"List-Archive",
56 "view archive of messages sent to the list",
57 "view the archive"}
61 char **
62 rfc2369_hdrs(char **hdrs)
64 int i;
66 for(i = 0; i < MLCMD_COUNT; i++)
67 hdrs[i] = rfc2369_fields[i].name;
69 hdrs[i] = NULL;
70 return(hdrs);
74 int
75 rfc2369_parse_fields(char *h, RFC2369_S *data)
77 char *ep, *nhp, *tp;
78 int i, rv = FALSE;
80 for(i = 0; i < MLCMD_COUNT; i++)
81 data[i].field = rfc2369_fields[i];
83 for(nhp = h; h; h = nhp){
84 /* coerce h to start of field */
85 for(ep = h;;)
86 if((tp = strpbrk(ep, "\015\012")) != NULL){
87 if(strindex(" \t", *((ep = tp) + 2))){
88 *ep++ = ' '; /* flatten continuation */
89 *ep++ = ' ';
90 for(; *ep; ep++) /* advance past whitespace */
91 if(*ep == '\t')
92 *ep = ' ';
93 else if(*ep != ' ')
94 break;
96 else{
97 *ep = '\0'; /* tie off header data */
98 nhp = ep + 2; /* start of next header */
99 break;
102 else{
103 while(*ep) /* find the end of this line */
104 ep++;
106 nhp = NULL; /* no more header fields */
107 break;
110 /* if length is within reason, see if we're interested */
111 if(ep - h < MLCMD_REASON && rfc2369_parse(h, data))
112 rv = TRUE;
115 return(rv);
120 rfc2369_parse(char *h, RFC2369_S *data)
122 int l, ifield, idata = 0;
123 char *p, *p1, *url, *comment;
125 /* look for interesting name's */
126 for(ifield = 0; ifield < MLCMD_COUNT; ifield++)
127 if(!struncmp(h, rfc2369_fields[ifield].name,
128 l = strlen(rfc2369_fields[ifield].name))
129 && *(h += l) == ':'){
130 /* unwrap any transport encodings */
131 if((p = (char *) rfc1522_decode_to_utf8((unsigned char *) tmp_20k_buf,
132 SIZEOF_20KBUF, ++h)) == tmp_20k_buf)
133 strcpy(h, p); /* assumption #383: decoding shrinks */
135 url = comment = NULL;
136 while(*h){
137 while(*h == ' ')
138 h++;
140 switch(*h){
141 case '<' : /* URL */
142 if((p = strindex(h, '>')) != NULL){
143 url = ++h; /* remember where it starts */
144 *p = '\0'; /* tie it off */
145 h = p + 1; /* advance h */
146 for(p = p1 = url; (*p1 = *p) != '\0'; p++)
147 if(*p1 != ' ')
148 p1++; /* remove whitespace ala RFC */
150 else
151 *h = '\0'; /* tie off junk */
153 break;
155 case '(' : /* Comment */
156 comment = rfc822_skip_comment(&h, LONGT);
157 break;
159 case 'N' : /* special case? */
160 case 'n' :
161 if(ifield == MLCMD_POST
162 && (*(h+1) == 'O' || *(h+1) == 'o')
163 && (!*(h+2) || *(h+2) == ' ')){
164 ; /* yup! */
166 url = h;
167 *(h + 2) = '\0';
168 h += 3;
169 break;
172 default :
173 removing_trailing_white_space(h);
174 if(!url
175 && (url = rfc1738_scan(h, &l))
176 && url == h && l == strlen(h)){
177 removing_trailing_white_space(h);
178 data[ifield].data[idata].value = url;
180 else
181 data[ifield].data[idata].error = h;
183 return(1); /* return junk */
186 while(*h == ' ')
187 h++;
189 switch(*h){
190 case ',' :
191 h++;
193 case '\0':
194 if(url || (comment && *comment)){
195 data[ifield].data[idata].value = url;
196 data[ifield].data[idata].comment = comment;
197 url = comment = NULL;
200 if(++idata == MLCMD_MAXDATA)
201 *h = '\0';
203 default :
204 break;
209 return(idata);