#include #include #include #include "gm-mcp.h" #include "gm-support.h" #include "gm-debug.h" #include "gm-string.h" gdouble gm_mcp_get_version(gdouble client_min, gdouble client_max, gdouble server_min, gdouble server_max) { if (client_max >= server_min && server_max >= client_min) { if (client_max < server_max) { return client_max; } else { return server_max; } } else { return 0.0; } } gchar const * gm_mcp_find_value(GList const *fields, gchar const *key) { GmKeyValuePair *tmp; while (fields) { tmp = (GmKeyValuePair *)(fields->data); if (strcasecmp(key, tmp->key) == 0) { return tmp->value; } fields = fields->next; } return NULL; } gchar * gm_mcp_escape_if_needed(gchar const *line) { GString *new_line; gchar const *ptr = line; gchar *result; if (*line == '\0') { return g_strdup("\"\""); } if (g_utf8_strchr(line, -1, ' ') || g_utf8_strchr(line, -1, '"') || g_utf8_strchr(line, -1, '\\')) { new_line = g_string_new("\""); while (*ptr != '\0') { if (*ptr == '"' || *ptr == '\\') { new_line = g_string_append_c(new_line, '\\'); } new_line = g_string_append_c(new_line, *ptr); ++ptr; } new_line = g_string_append_c(new_line, '"'); result = new_line->str; g_string_free(new_line, FALSE); return result; } else { return g_strdup(line); } } gchar * gm_mcp_un_escape(gchar *line) { gchar *ptri = line, *ptrj = line; gboolean shifted = FALSE; while (*ptri != '\0') { if (*ptri == '\\') { shifted = TRUE; ++ptri; } if (shifted) { *ptrj = *ptri; } ++ptrj; ++ptri; } *ptrj = '\0'; return line; } gchar const * gm_mcp_process_keyval(GList **info, gchar const *line) { gchar const *keystart; gchar const *valuestart; int keylen, valuelen; GmKeyValuePair *newKeyValue; if (*line != ' ' || line[1] == '\0' || line[1] == ' ') { return NULL; } keystart = ++line; gm_string_skip_till(&line, ": "); if (*line != ':') { return NULL; } keylen = line - keystart; line = g_utf8_next_char(line); if (line[1] == '\0' || *line != ' ') { return NULL; } line = g_utf8_next_char(line); if (*line == ' ') { return NULL; } valuestart = line; if (*line == '"') { ++valuestart; ++line; while (*line != '\0' && *line != '"') { if (*line == '\\') { ++line; } ++line; } valuelen = line - valuestart; if (*line != '"') { --valuelen; } else { ++line; } } else { gm_string_skip_nonspace(&line); valuelen = line - valuestart; } newKeyValue = g_new(GmKeyValuePair, 1); newKeyValue->key = g_strndup(keystart, keylen); newKeyValue->value = gm_mcp_un_escape(g_strndup(valuestart, valuelen)); *info = g_list_append(*info, newKeyValue); return line; } GList * gm_mcp_process_key_values(gchar const *line) { GList *result = NULL; while (line && *line != '\0') { line = gm_mcp_process_keyval(&result, line); } return result; } gboolean gm_mcp_parse_line(gchar *line, McpMessageInfo *info) { gchar *p = g_utf8_strchr(line, -1, ' '); if (!p || p == line) { return FALSE; } info->name = g_strndup(line, (p - line)); line = p + 1; // Now there should be a authentication key! p = g_utf8_strchr(line, -1, ' '); if (!p) { p = line + strlen(line); } info->authkey = g_strndup(line, (p - line)); // Now process the keyvals info->fields = gm_mcp_process_key_values(p); return TRUE; } gchar * gm_mcp_generate_key(gint len) { gchar *s = g_malloc(len + 1); gchar ref[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"; gint n = strlen(ref); gint i; srand((int) time(NULL)); for (i = 0; i < len; i++) { s[i] = ref[rand() % n]; } s[i] = 0; return s; } gchar * gm_mcp_generate_data_tag() { return gm_mcp_generate_key(10); } gchar * gm_mcp_generate_auth_key() { return gm_mcp_generate_key(6); } gchar const * gm_mcp_find_multiline_tag(GList const *fields) { GmKeyValuePair *data; gunichar last; while (fields) { data = (GmKeyValuePair *)(fields->data); last = g_utf8_get_char(g_utf8_prev_char(data->key + strlen(data->key))); if (last == '*') { return data->key; } fields = fields->next; } return NULL; } void gm_mcp_destroy_fields(GList *fields) { GmKeyValuePair *tmp; GList *elem = fields; while (elem) { tmp = (GmKeyValuePair *) (elem->data); g_free(tmp->key); g_free(tmp->value); g_free(elem->data); elem->data = NULL; elem = elem->next; } g_list_free(fields); } void gm_mcp_list_free(GList *list) { gm_g_list_free_simple(list); } GList * gm_mcp_parse_list(gchar const *s) { GList *result = NULL; gchar item_mem[strlen(s) + 1]; gchar *item; gunichar c, cn; gchar *next_char; while (*s != '\0') { gm_string_skip_space(&s); item = item_mem; *item = '\0'; while (*s != '\0') { c = g_utf8_get_char(s); next_char = g_utf8_next_char(s); cn = g_utf8_get_char(next_char); if (g_unichar_isspace(c)) { break; } if (c == '\\' && cn != '\0') { c = cn; next_char = g_utf8_next_char(next_char); } item += g_unichar_to_utf8(c, item); s = next_char; } *item = '\0'; result = g_list_append(result, g_strdup(item_mem)); } return result; }