+ if (encoded) {
+ /*
+ * Single quotes delimit the character set and language tag.
+ * They are required on the first section (or a complete
+ * parameter).
+ */
+ if (index == 0) {
+ vp = dp;
+ while (*vp != '\'' && !isspace((unsigned char) *vp) &&
+ *vp != '\0')
+ vp++;
+ if (*vp == '\'') {
+ if (vp != dp) {
+ len = vp - dp;
+ charset = mh_xmalloc(len + 1);
+ strncpy(charset, dp, len);
+ charset[len] = '\0';
+ } else {
+ charset = NULL;
+ }
+ vp++;
+ } else {
+ advise(NULL, "missing charset in message %s's %s: "
+ "field\n%*s(parameter %s)", filename, fieldname,
+ strlen(invo_name) + 2, "", nameptr);
+ free(nameptr);
+ return NOTOK;
+ }
+ dp = vp;
+
+ while (*vp != '\'' && !isspace((unsigned char) *vp) &&
+ *vp != '\0')
+ vp++;
+
+ if (*vp == '\'') {
+ if (vp != dp) {
+ len = vp - dp;
+ lang = mh_xmalloc(len + 1);
+ strncpy(lang, dp, len);
+ lang[len] = '\0';
+ } else {
+ lang = NULL;
+ }
+ vp++;
+ } else {
+ advise(NULL, "missing language tag in message %s's %s: "
+ "field\n%*s(parameter %s)", filename, fieldname,
+ strlen(invo_name) + 2, "", nameptr);
+ free(nameptr);
+ if (charset)
+ free(charset);
+ return NOTOK;
+ }
+
+ dp = vp;
+ }
+
+ /*
+ * At this point vp should be pointing at the beginning
+ * of the encoded value/section. Continue until we reach
+ * the end or get whitespace. But first, calculate the
+ * length so we can allocate the correct buffer size.
+ */
+
+ for (vp = dp, len = 0; istoken(*vp); vp++) {
+ if (*vp == '%') {
+ if (*(vp + 1) == '\0' ||
+ !isxdigit((unsigned char) *(vp + 1)) ||
+ *(vp + 2) == '\0' ||
+ !isxdigit((unsigned char) *(vp + 2))) {
+ advise(NULL, "invalid encoded sequence in message "
+ "%s's %s: field\n%*s(parameter %s)",
+ filename, fieldname, strlen(invo_name) + 2,
+ "", nameptr);
+ free(nameptr);
+ if (charset)
+ free(charset);
+ if (lang)
+ free(lang);
+ return NOTOK;
+ }
+ vp += 2;
+ }
+ len++;
+ }
+
+ up = valptr = mh_xmalloc(len + 1);
+
+ for (vp = dp; istoken(*vp); vp++) {
+ if (*vp == '%') {
+ *up++ = decode_qp(*(vp + 1), *(vp + 2));
+ vp += 2;
+ } else {
+ *up++ = *vp;
+ }
+ }
+
+ *up = '\0';
+ cp = vp;
+ } else {
+ /*
+ * A "normal" string. If it's got a leading quote, then we
+ * strip the quotes out. Otherwise go until we reach the end
+ * or get whitespace. Note we scan it twice; once to get the
+ * length, then the second time copies it into the destination
+ * buffer.
+ */