@@ -1002,39 +1002,100 @@ static void translatechars(char *start, char *end, struct Push *buff)
1002
1002
}
1003
1003
}
1004
1004
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 )
1006
1014
{
1007
- char * p ;
1008
- struct Push buff ;
1009
- unsigned int i ;
1010
- char hexa [5 ];
1011
1015
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 ;
1013
1057
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 ;
1024
1066
}
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 ;
1035
1082
}
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
+ }
1036
1096
}
1037
- RETURN_PUSH (buff );
1097
+ }
1098
+ RETURN_PUSH (buff );
1038
1099
}
1039
1100
1040
1101
/* Given a string, replaces all instances of "oldpiece" with "newpiece".
@@ -1123,54 +1184,57 @@ char *replacechar(char *string, char old, char *new)
1123
1184
1124
1185
char * makemailcommand (char * mailcommand , char * email , char * id , char * subject )
1125
1186
{
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
+ }
1165
1200
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 );
1169
1218
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 );
1171
1236
1172
- free (convsubj );
1173
- return newcmd ;
1237
+ return newcmd2 ;
1174
1238
}
1175
1239
1176
1240
char * unspamify (char * s )
@@ -1470,7 +1534,9 @@ char *parseurl(char *input, char *charset)
1470
1534
}
1471
1535
}
1472
1536
if (accepted ) {
1473
- char * urlbuff2 = translateurl (urlbuff );
1537
+ /* string is already escaped in URI context */
1538
+ char * urlbuff2 = convcharsnospamprotect (urlbuff ,"us-ascii" );
1539
+
1474
1540
trio_snprintf (tempbuff , sizeof (tempbuff ),
1475
1541
"<a href=\"%s%s\">%s%s</a>" ,
1476
1542
thisprotocol , urlbuff2 , thisprotocol , urlbuff2 );
0 commit comments