+static int
+_mech_plus_p(const char *mech, size_t len)
+{
+ return (len > 5 && strncasecmp(&mech[len - 5], "-PLUS", 5) == 0);
+}
+
+/*
+ * Order PLUS mechanisms first. Returns NUL separated list of
+ * *count items.
+ */
+static int
+_sasl_client_order_mechs(const sasl_utils_t *utils,
+ const char *mechs,
+ int has_cb_data,
+ char **ordered_mechs,
+ size_t *count,
+ int *server_can_cb)
+{
+ char *list, *listp;
+ size_t i;
+ const char *p, *start = NULL;
+
+ *count = 0;
+ *server_can_cb = 0;
+
+ listp = list = utils->malloc(strlen(mechs) + 1);
+ if (list == NULL)
+ return SASL_NOMEM;
+
+ if (has_cb_data) {
+ for (start = p = mechs, i = 0; *p != '\0'; p++) {
+ if (isspace(*p) || p[1] == '\0') {
+ size_t len = p - start + 1;
+
+ if (_mech_plus_p(start, len)) {
+ memcpy(listp, start, len);
+ listp[len] = '\0';
+ listp += len + 1;
+ (*count)++;
+ *server_can_cb = 1;
+ }
+ start = p + 1;
+ }
+ }
+ }
+
+ for (start = p = mechs, i = 0; *p != '\0'; p++) {
+ if (isspace(*p) || p[1] == '\0') {
+ size_t len = p - start + 1;
+
+ if (!_mech_plus_p(start, len)) {
+ memcpy(listp, start, len);
+ listp[len] = '\0';
+ listp += len + 1;
+ (*count)++;
+ }
+ start = p + 1;
+ }
+ }
+
+ *listp = '\0';
+ *ordered_mechs = list;
+
+ return SASL_OK;
+}
+