Skip to content

Commit ee16aba

Browse files
author
Daigo Matsubara
committed
replaced makemailcommand() and translateurl() to output valid URI string, from now translateurl() escapes URI strings only.
1 parent 0d553e0 commit ee16aba

File tree

1 file changed

+139
-73
lines changed

1 file changed

+139
-73
lines changed

src/string.c

Lines changed: 139 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,39 +1002,100 @@ static void translatechars(char *start, char *end, struct Push *buff)
10021002
}
10031003
}
10041004

1005-
static char *translateurl(char *url)
1005+
1006+
/*
1007+
* translateurl(), to escape URI strings only.
1008+
* this should be divided from convchars().
1009+
*
1010+
* in_mailcommand: line is MAILCOMMAND, if 1
1011+
*
1012+
*/
1013+
static char *translateurl(char *line, int in_mailcommand)
10061014
{
1007-
char *p;
1008-
struct Push buff;
1009-
unsigned int i;
1010-
char hexa[5];
10111015

1012-
INIT_PUSH(buff);
1016+
int hexbuflen;
1017+
char hexbuf[16];
1018+
struct Push buff;
1019+
INIT_PUSH(buff); /* init macro */
1020+
1021+
for(; *line; line++){
1022+
if(isalnum((int)*line)){
1023+
PushByte(&buff,*line);
1024+
}else{
1025+
switch (*line){
1026+
/* we can use unreserved characters, others should be escaped */
1027+
/* RFC2396: */
1028+
/* unreserved = alphanum | mark */
1029+
/* mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" */
1030+
case '-':
1031+
PushByte(&buff,*line);
1032+
break;
1033+
case '_':
1034+
PushByte(&buff,*line);
1035+
break;
1036+
case '.':
1037+
PushByte(&buff,*line);
1038+
break;
1039+
case '!':
1040+
PushByte(&buff,*line);
1041+
break;
1042+
case '~':
1043+
PushByte(&buff,*line);
1044+
break;
1045+
case '*':
1046+
PushByte(&buff,*line);
1047+
break;
1048+
case '\'':
1049+
PushByte(&buff,*line);
1050+
break;
1051+
case '(':
1052+
PushByte(&buff,*line);
1053+
break;
1054+
case ')':
1055+
PushByte(&buff,*line);
1056+
break;
10131057

1014-
for (p = url; *p; p++) {
1015-
if (*p == '&')
1016-
PushString(&buff, "&");
1017-
else if (*p == '@' && set_mailcommand) /* we need to code @ as such to
1018-
avoid a misconvertion */
1019-
PushString(&buff, "@");
1020-
else if ((unsigned char) *p > 127 && set_mailcommand) {
1021-
i = (unsigned char) *p & 0xFF;
1022-
snprintf (hexa, sizeof (hexa) -1, "%%%02x", i);
1023-
PushString (&buff, hexa);
1058+
/*
1059+
* following characters are reserved, but used in MAILCOMMAND
1060+
*/
1061+
1062+
case ':':
1063+
if (in_mailcommand){
1064+
PushByte(&buff,*line);
1065+
break;
10241066
}
1025-
else {
1026-
/* JK: reaching this point means that we didn't need to do any of the
1027-
special conversions for URLs, but we still need to make
1028-
sure that it's a valid character. */
1029-
char s[2] = "a";
1030-
char *ptr;
1031-
s[0] = *p;
1032-
ptr = convchars (s, NULL);
1033-
PushString (&buff, ptr);
1034-
free (ptr);
1067+
case '?':
1068+
if (in_mailcommand){
1069+
PushByte(&buff,*line);
1070+
break;
1071+
}
1072+
case '&':
1073+
if (in_mailcommand){
1074+
/* ...to reduce CPU cycles */
1075+
PushString(&buff,"&");
1076+
break;
1077+
}
1078+
case '=':
1079+
if (in_mailcommand){
1080+
PushByte(&buff,*line);
1081+
break;
10351082
}
1083+
case '$':
1084+
if (in_mailcommand){
1085+
PushByte(&buff,*line);
1086+
break;
1087+
}
1088+
1089+
default:
1090+
/* URIs MUST NOT have non-ascii characters */
1091+
/* otherwise, we must use IRI */
1092+
hexbuflen=snprintf(hexbuf,4,"%%%02X",*line);
1093+
PushString(&buff,hexbuf);
1094+
break;
1095+
}
10361096
}
1037-
RETURN_PUSH(buff);
1097+
}
1098+
RETURN_PUSH(buff);
10381099
}
10391100

10401101
/* Given a string, replaces all instances of "oldpiece" with "newpiece".
@@ -1123,54 +1184,57 @@ char *replacechar(char *string, char old, char *new)
11231184

11241185
char *makemailcommand(char *mailcommand, char *email, char *id, char *subject)
11251186
{
1126-
int hasre;
1127-
char *cp;
1128-
char *tmpsubject;
1129-
char *convsubj;
1130-
1131-
char *newcmd = NULL;
1132-
char *newcmd2;
1133-
1134-
if (subject && isre(subject, NULL))
1135-
hasre = 1;
1136-
else
1137-
hasre = 0;
1138-
1139-
convsubj = convchars(subject, NULL);
1140-
1141-
/* remade to deal with any-length strings */
1142-
/* tmpsubject = maprintf("%s%s", (hasre) ? "" : "Re: ", (convsubj) ? convsubj : ""); */
1143-
trio_asprintf(&tmpsubject, "%s%s", (convsubj && !hasre)
1144-
? "Re: " : "", (convsubj) ? convsubj : "");
1145-
1146-
1147-
if ((cp = strrchr(email, ' ')) != NULL)
1148-
*cp = '\0';
1149-
1150-
newcmd = replace(mailcommand, "$TO", email);
1151-
newcmd2 = replace(newcmd, "$ID", id);
1152-
free(newcmd);
1153-
1154-
newcmd = replace(newcmd2, "$SUBJECT", (tmpsubject) ? tmpsubject : "");
1155-
free(newcmd2);
1156-
1157-
newcmd2 = replacechar(newcmd, '%', "%25");
1158-
free(newcmd);
1159-
1160-
newcmd = replacechar(newcmd2, ' ', "%20");
1161-
free(newcmd2);
1162-
1163-
newcmd2 = replacechar(newcmd, '+', "%2B");
1164-
free(newcmd);
1187+
char *newcmd = NULL, *newcmd2=NULL, *cp;
1188+
char *tmpsubject=NULL;
1189+
char *convsubj=NULL,*convemail=NULL,*convid=NULL;
1190+
1191+
if ((cp = strrchr(email, ' ')) != NULL)
1192+
*cp = '\0';
1193+
1194+
/* prepare "Re: " string, should this be localized? */
1195+
if(subject && isre(subject,NULL)){
1196+
trio_asprintf(&tmpsubject, "%s",subject);
1197+
}else{
1198+
trio_asprintf(&tmpsubject, "Re: %s",subject);
1199+
}
11651200

1166-
/* escape the special characters following the URL convention */
1167-
newcmd = translateurl (newcmd2);
1168-
free (newcmd2);
1201+
/* escape strings */
1202+
convsubj=translateurl(tmpsubject,0);
1203+
free(tmpsubject);
1204+
convemail=translateurl(email,0);
1205+
convid=translateurl(id,0);
1206+
1207+
/* escape mailcommand, with keeping some delimiters */
1208+
newcmd = translateurl(mailcommand,1);
1209+
1210+
/* put email address */
1211+
if (strlen(email)>0){
1212+
newcmd2 = replace(newcmd, "$TO", convemail);
1213+
}else{
1214+
newcmd2 = replace(newcmd, "$TO", "");
1215+
}
1216+
free(convemail);
1217+
free(newcmd);
11691218

1170-
free(tmpsubject);
1219+
/* put message-id */
1220+
if (strlen(id)>0){
1221+
newcmd = replace(newcmd2, "$ID", convid);
1222+
}else{
1223+
newcmd = replace(newcmd2, "$ID", "");
1224+
}
1225+
free(convid);
1226+
free(newcmd2);
1227+
1228+
/* put subject */
1229+
if (strlen(subject)>0){
1230+
newcmd2 = replace(newcmd, "$SUBJECT", convsubj);
1231+
}else{
1232+
newcmd2 = replace(newcmd, "$SUBJECT", "");
1233+
}
1234+
free(newcmd);
1235+
free(convsubj);
11711236

1172-
free(convsubj);
1173-
return newcmd;
1237+
return newcmd2;
11741238
}
11751239

11761240
char *unspamify(char *s)
@@ -1470,7 +1534,9 @@ char *parseurl(char *input, char *charset)
14701534
}
14711535
}
14721536
if(accepted) {
1473-
char *urlbuff2 = translateurl(urlbuff);
1537+
/* string is already escaped in URI context */
1538+
char *urlbuff2 = convcharsnospamprotect(urlbuff,"us-ascii");
1539+
14741540
trio_snprintf(tempbuff, sizeof(tempbuff),
14751541
"<a href=\"%s%s\">%s%s</a>",
14761542
thisprotocol, urlbuff2, thisprotocol, urlbuff2);

0 commit comments

Comments
 (0)