2005-11-07 10:56:25 +01:00
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#include "gm-mcp.h"
|
2006-01-10 01:41:39 +01:00
|
|
|
#include "gm-support.h"
|
|
|
|
#include "gm-debug.h"
|
|
|
|
#include "gm-string.h"
|
2005-11-07 10:56:25 +01:00
|
|
|
|
|
|
|
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;
|
2006-04-07 18:32:44 +02:00
|
|
|
} else {
|
|
|
|
return server_max;
|
2005-11-07 10:56:25 +01:00
|
|
|
}
|
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
|
2005-11-15 12:42:10 +01:00
|
|
|
gchar const *
|
|
|
|
gm_mcp_process_keyval(GList **info, gchar const *line) {
|
|
|
|
gchar const *keystart;
|
|
|
|
gchar const *valuestart;
|
2005-11-07 10:56:25 +01:00
|
|
|
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 *
|
2005-11-15 12:42:10 +01:00
|
|
|
gm_mcp_process_key_values(gchar const *line) {
|
2005-11-07 10:56:25 +01:00
|
|
|
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);
|
|
|
|
}
|
2005-11-15 12:42:10 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|