+
+/*
+ * Output an encoded parameter string.
+ */
+
+static size_t
+encode_param(PM pm, char *output, size_t len, size_t valuelen,
+ size_t valueoff, int index)
+{
+ size_t outlen = 0, n;
+ char *endptr = output + len, *p;
+
+ /*
+ * First, output the marker for an encoded string.
+ */
+
+ *output++ = '*';
+ *output++ = '=';
+ outlen += 2;
+
+ /*
+ * If the index is 0, output the character set and language tag.
+ * If theses were NULL, they should have already been filled in
+ * by param_len().
+ */
+
+ if (index == 0) {
+ n = snprintf(output, len - outlen, "%s'%s'", pm->pm_charset,
+ pm->pm_lang);
+ output += n;
+ outlen += n;
+ if (output > endptr) {
+ advise(NULL, "Internal error: parameter buffer overflow");
+ return 0;
+ }
+ }
+
+ /*
+ * Copy over the value, encoding if necessary
+ */
+
+ p = pm->pm_value + valueoff;
+ while (valuelen-- > 0) {
+ if (isparamencode(*p)) {
+ n = snprintf(output, len - outlen, "%%%02X", (unsigned char) *p++);
+ output += n;
+ outlen += n;
+ } else {
+ *output++ = *p++;
+ outlen++;
+ }
+ if (output > endptr) {
+ advise(NULL, "Internal error: parameter buffer overflow");
+ return 0;
+ }
+ }
+
+ *output = '\0';
+
+ return outlen;
+}
+
+/*
+ * Output a "normal" parameter, without encoding. Be sure to escape
+ * quotes and backslashes if necessary.
+ */
+
+static size_t
+normal_param(PM pm, char *output, size_t len, size_t valuelen,
+ size_t valueoff)
+{
+ size_t outlen = 0;
+ char *endptr = output + len, *p;
+
+ *output++ = '=';
+ *output++ = '"';
+ outlen += 2;
+
+ p = pm->pm_value + valueoff;
+
+ while (valuelen-- > 0) {
+ switch (*p) {
+ case '\\':
+ case '"':
+ *output++ = '\\';
+ outlen++;
+ default:
+ *output++ = *p++;
+ outlen++;
+ }
+ if (output > endptr) {
+ advise(NULL, "Internal error: parameter buffer overflow");
+ return 0;
+ }
+ }
+
+ if (output - 2 > endptr) {
+ advise(NULL, "Internal error: parameter buffer overflow");
+ return 0;
+ }
+
+ *output++ = '"';
+ *output++ = '\0';
+
+ return outlen + 1;
+}
+
+/*
+ * Add a parameter to the parameter linked list
+ */
+
+PM
+add_param(PM *first, PM *last, const char *name, const char *value)
+{
+ PM pm = mh_xmalloc(sizeof(*pm));
+
+ memset(pm, 0, sizeof(*pm));
+
+ pm->pm_name = getcpy(name);
+ pm->pm_value = getcpy(value);
+
+ if (*first) {
+ (*last)->pm_next = pm;
+ *last = pm;
+ } else {
+ *first = pm;
+ *last = pm;
+ }
+
+ return pm;
+}