+
+static const char *cf_pair_print_value(const CONF_PAIR *cp,
+ char *buffer, size_t buflen)
+{
+ char *p;
+
+ if (!cp->value) return "";
+
+ switch (cp->value_type) {
+ default:
+ case T_BARE_WORD:
+ snprintf(buffer, buflen, "%s", cp->value);
+ break;
+
+ case T_SINGLE_QUOTED_STRING:
+ snprintf(buffer, buflen, "'%s'", cp->value);
+ break;
+
+ case T_DOUBLE_QUOTED_STRING:
+ buffer[0] = '"';
+ fr_print_string(cp->value, strlen(cp->value),
+ buffer + 1, buflen - 3);
+ p = buffer + strlen(buffer); /* yuck... */
+ p[0] = '"';
+ p[1] = '\0';
+ break;
+ }
+
+ return buffer;
+}
+
+
+int cf_pair2xml(FILE *fp, const CONF_PAIR *cp)
+{
+ fprintf(fp, "<%s>", cp->attr);
+ if (cp->value) {
+ char buffer[2048];
+
+ char *p = buffer;
+ const char *q = cp->value;
+
+ while (*q && (p < (buffer + sizeof(buffer) - 1))) {
+ if (q[0] == '&') {
+ memcpy(p, "&", 4);
+ p += 5;
+
+ } else if (q[0] == '<') {
+ memcpy(p, "<", 4);
+ p += 4;
+
+ } else if (q[0] == '>') {
+ memcpy(p, ">", 4);
+ p += 4;
+
+ } else {
+ *(p++) = *q;
+ }
+ q++;
+ }
+
+ *p = '\0';
+ fprintf(fp, "%s", buffer);
+ }
+
+ fprintf(fp, "</%s>\n", cp->attr);
+
+ return 1;
+}
+
+int cf_section2xml(FILE *fp, const CONF_SECTION *cs)
+{
+ CONF_ITEM *ci, *next;
+
+ /*
+ * Section header
+ */
+ fprintf(fp, "<%s>\n", cs->name1);
+ if (cs->name2) {
+ fprintf(fp, "<_name2>%s</_name2>\n", cs->name2);
+ }
+
+ /*
+ * Loop over contents.
+ */
+ for (ci = cs->children; ci; ci = next) {
+ next = ci->next;
+
+ switch (ci->type) {
+ case CONF_ITEM_PAIR:
+ if (!cf_pair2xml(fp, (CONF_PAIR *) ci)) return 0;
+ break;
+
+ case CONF_ITEM_SECTION:
+ if (!cf_section2xml(fp, (CONF_SECTION *) ci)) return 0;
+ break;
+
+ default: /* should really be an error. */
+ break;
+
+ }
+ }
+
+ fprintf(fp, "</%s>\n", cs->name1);
+
+ return 1; /* success */
+}
+
+int cf_pair2file(FILE *fp, const CONF_PAIR *cp)
+{
+ char buffer[2048];
+
+ fprintf(fp, "\t%s = %s\n", cp->attr,
+ cf_pair_print_value(cp, buffer, sizeof(buffer)));
+
+ return 1;
+}
+
+int cf_section2file(FILE *fp, const CONF_SECTION *cs)
+{
+ const CONF_ITEM *ci, *next;
+
+ /*
+ * Section header
+ */
+ if (!cs->name2) {
+ fprintf(fp, "%s {\n", cs->name1);
+ } else {
+ fprintf(fp, "%s %s {\n",
+ cs->name1, cs->name2);
+ }
+
+ /*
+ * Loop over contents.
+ */
+ for (ci = cs->children; ci; ci = next) {
+ next = ci->next;
+
+ switch (ci->type) {
+ case CONF_ITEM_PAIR:
+ if (!cf_pair2file(fp, (const CONF_PAIR *) ci)) return 0;
+ break;
+
+ case CONF_ITEM_SECTION:
+ if (!cf_section2file(fp, (const CONF_SECTION *) ci)) return 0;
+ break;
+
+ default: /* should really be an error. */
+ break;
+
+ }
+ }
+
+ fprintf(fp, "}\n");
+
+ return 1; /* success */
+}