示例#1
0
static gfire_game_configuration *gfire_game_configuration_create_from_xml(xmlnode *p_node)
{
	xmlnode *command_node = xmlnode_get_child(p_node, "command");
	if(!command_node)
		return NULL;

	gfire_game_configuration *ret = g_malloc0(sizeof(gfire_game_configuration));

	if(xmlnode_get_attrib(p_node, "id"))
		sscanf(xmlnode_get_attrib(p_node, "id"), "%u", &ret->game_id);

	xmlnode *cur_node = xmlnode_get_child(command_node, "detect");
	if(cur_node)
		ret->detect_file = xmlnode_get_data_unescaped(cur_node);

	cur_node = xmlnode_get_child(command_node, "launch");
	if(cur_node)
		ret->launch_file = xmlnode_get_data_unescaped(cur_node);

	cur_node = xmlnode_get_child(command_node, "prefix");
	if(cur_node)
		ret->launch_prefix = xmlnode_get_data_unescaped(cur_node);

	return ret;
}
示例#2
0
/**
 * This function parses the given response from a clientLogin request
 * and extracts the useful information.
 *
 * @param gc           The PurpleConnection.  If the response data does
 *                     not indicate then purple_connection_error_reason()
 *                     will be called to close this connection.
 * @param response     The response data from the clientLogin request.
 * @param response_len The length of the above response, or -1 if
 *                     @response is NUL terminated.
 * @param token        If parsing was successful then this will be set to
 *                     a newly allocated string containing the token.  The
 *                     caller should g_free this string when it is finished
 *                     with it.  On failure this value will be untouched.
 * @param secret       If parsing was successful then this will be set to
 *                     a newly allocated string containing the secret.  The
 *                     caller should g_free this string when it is finished
 *                     with it.  On failure this value will be untouched.
 * @param hosttime     If parsing was successful then this will be set to
 *                     the time on the OpenAuth Server in seconds since the
 *                     Unix epoch.  On failure this value will be untouched.
 *
 * @return TRUE if the request was successful and we were able to
 *         extract all info we need.  Otherwise FALSE.
 */
static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **token, char **secret, time_t *hosttime)
{
    xmlnode *response_node, *tmp_node, *data_node;
    xmlnode *secret_node = NULL, *hosttime_node = NULL, *token_node = NULL, *tokena_node = NULL;
    char *tmp;

    /* Parse the response as XML */
    response_node = xmlnode_from_str(response, response_len);
    if (response_node == NULL)
    {
        char *msg;
        purple_debug_error("oscar", "clientLogin could not parse "
                           "response as XML: %s\n", response);
        msg = generate_error_message(response_node,
                                     URL_CLIENT_LOGIN);
        purple_connection_error_reason(gc,
                                       PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
        g_free(msg);
        return FALSE;
    }

    /* Grab the necessary XML nodes */
    tmp_node = xmlnode_get_child(response_node, "statusCode");
    data_node = xmlnode_get_child(response_node, "data");
    if (data_node != NULL) {
        secret_node = xmlnode_get_child(data_node, "sessionSecret");
        hosttime_node = xmlnode_get_child(data_node, "hostTime");
        token_node = xmlnode_get_child(data_node, "token");
        if (token_node != NULL)
            tokena_node = xmlnode_get_child(token_node, "a");
    }

    /* Make sure we have a status code */
    if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
        char *msg;
        purple_debug_error("oscar", "clientLogin response was "
                           "missing statusCode: %s\n", response);
        msg = generate_error_message(response_node,
                                     URL_CLIENT_LOGIN);
        purple_connection_error_reason(gc,
                                       PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
        g_free(msg);
        xmlnode_free(response_node);
        return FALSE;
    }

    /* Make sure the status code was 200 */
    if (strcmp(tmp, "200") != 0)
    {
        int status_code, status_detail_code = 0;

        status_code = atoi(tmp);
        g_free(tmp);
        tmp_node = xmlnode_get_child(response_node, "statusDetailCode");
        if (tmp_node != NULL && (tmp = xmlnode_get_data_unescaped(tmp_node)) != NULL) {
            status_detail_code = atoi(tmp);
            g_free(tmp);
        }

        purple_debug_error("oscar", "clientLogin response statusCode "
                           "was %d (%d): %s\n", status_code, status_detail_code, response);

        if (status_code == 330 && status_detail_code == 3011) {
            PurpleAccount *account = purple_connection_get_account(gc);
            if (!purple_account_get_remember_password(account))
                purple_account_set_password(account, NULL);
            purple_connection_error_reason(gc,
                                           PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
                                           _("Incorrect password"));
        } else if (status_code == 330 && status_detail_code == 3015) {
            purple_connection_error_reason(gc,
                                           PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
                                           _("Server requested that you fill out a CAPTCHA in order to "
                                             "sign in, but this client does not currently support CAPTCHAs."));
        } else if (status_code == 401 && status_detail_code == 3019) {
            purple_connection_error_reason(gc,
                                           PURPLE_CONNECTION_ERROR_OTHER_ERROR,
                                           _("AOL does not allow your screen name to authenticate here"));
        } else {
            char *msg;
            msg = generate_error_message(response_node,
                                         URL_CLIENT_LOGIN);
            purple_connection_error_reason(gc,
                                           PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
            g_free(msg);
        }

        xmlnode_free(response_node);
        return FALSE;
    }
    g_free(tmp);

    /* Make sure we have everything else */
    if (data_node == NULL || secret_node == NULL ||
            token_node == NULL || tokena_node == NULL)
    {
        char *msg;
        purple_debug_error("oscar", "clientLogin response was missing "
                           "something: %s\n", response);
        msg = generate_error_message(response_node,
                                     URL_CLIENT_LOGIN);
        purple_connection_error_reason(gc,
                                       PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
        g_free(msg);
        xmlnode_free(response_node);
        return FALSE;
    }

    /* Extract data from the XML */
    *token = xmlnode_get_data_unescaped(tokena_node);
    *secret = xmlnode_get_data_unescaped(secret_node);
    tmp = xmlnode_get_data_unescaped(hosttime_node);
    if (*token == NULL || **token == '\0' || *secret == NULL || **secret == '\0' || tmp == NULL || *tmp == '\0')
    {
        char *msg;
        purple_debug_error("oscar", "clientLogin response was missing "
                           "something: %s\n", response);
        msg = generate_error_message(response_node,
                                     URL_CLIENT_LOGIN);
        purple_connection_error_reason(gc,
                                       PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
        g_free(msg);
        g_free(*token);
        g_free(*secret);
        g_free(tmp);
        xmlnode_free(response_node);
        return FALSE;
    }

    *hosttime = strtol(tmp, NULL, 10);
    g_free(tmp);

    xmlnode_free(response_node);

    return TRUE;
}
示例#3
0
static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **host, unsigned short *port, char **cookie, char **tls_certname)
{
    xmlnode *response_node, *tmp_node, *data_node;
    xmlnode *host_node = NULL, *port_node = NULL, *cookie_node = NULL, *tls_node = NULL;
    gboolean use_tls;
    char *tmp;
    guint code;

    use_tls = purple_account_get_bool(purple_connection_get_account(gc), "use_ssl", OSCAR_DEFAULT_USE_SSL);

    /* Parse the response as XML */
    response_node = xmlnode_from_str(response, response_len);
    if (response_node == NULL)
    {
        char *msg;
        purple_debug_error("oscar", "startOSCARSession could not parse "
                           "response as XML: %s\n", response);
        /* Note to translators: %s in this string is a URL */
        msg = generate_error_message(response_node,
                                     URL_START_OSCAR_SESSION);
        purple_connection_error_reason(gc,
                                       PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
        g_free(msg);
        return FALSE;
    }

    /* Grab the necessary XML nodes */
    tmp_node = xmlnode_get_child(response_node, "statusCode");
    data_node = xmlnode_get_child(response_node, "data");
    if (data_node != NULL) {
        host_node = xmlnode_get_child(data_node, "host");
        port_node = xmlnode_get_child(data_node, "port");
        cookie_node = xmlnode_get_child(data_node, "cookie");
        tls_node = xmlnode_get_child(data_node, "tlsCertName");
    }

    /* Make sure we have a status code */
    if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
        char *msg;
        purple_debug_error("oscar", "startOSCARSession response was "
                           "missing statusCode: %s\n", response);
        msg = generate_error_message(response_node,
                                     URL_START_OSCAR_SESSION);
        purple_connection_error_reason(gc,
                                       PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
        g_free(msg);
        xmlnode_free(response_node);
        return FALSE;
    }

    /* Make sure the status code was 200 */
    code = atoi(tmp);
    if (code != 200)
    {
        xmlnode *status_detail_node;
        guint status_detail = 0;

        status_detail_node = xmlnode_get_child(response_node,
                                               "statusDetailCode");
        if (status_detail_node) {
            gchar *data = xmlnode_get_data(status_detail_node);
            if (data) {
                status_detail = atoi(data);
                g_free(data);
            }
        }

        purple_debug_error("oscar", "startOSCARSession response statusCode "
                           "was %s: %s\n", tmp, response);

        if ((code == 401 && status_detail != 1014) || code == 607)
            purple_connection_error_reason(gc,
                                           PURPLE_CONNECTION_ERROR_OTHER_ERROR,
                                           _("You have been connecting and disconnecting too "
                                             "frequently. Wait ten minutes and try again. If "
                                             "you continue to try, you will need to wait even "
                                             "longer."));
        else {
            char *msg;
            msg = generate_error_message(response_node,
                                         URL_START_OSCAR_SESSION);
            purple_connection_error_reason(gc,
                                           PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
            g_free(msg);
        }

        g_free(tmp);
        xmlnode_free(response_node);
        return FALSE;
    }
    g_free(tmp);

    /* Make sure we have everything else */
    if (data_node == NULL || host_node == NULL ||
            port_node == NULL || cookie_node == NULL ||
            (use_tls && tls_node == NULL))
    {
        char *msg;
        purple_debug_error("oscar", "startOSCARSession response was missing "
                           "something: %s\n", response);
        msg = generate_error_message(response_node,
                                     URL_START_OSCAR_SESSION);
        purple_connection_error_reason(gc,
                                       PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
        g_free(msg);
        xmlnode_free(response_node);
        return FALSE;
    }

    /* Extract data from the XML */
    *host = xmlnode_get_data_unescaped(host_node);
    tmp = xmlnode_get_data_unescaped(port_node);
    *cookie = xmlnode_get_data_unescaped(cookie_node);

    if (use_tls)
        *tls_certname = xmlnode_get_data_unescaped(tls_node);

    if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || *cookie == NULL || **cookie == '\0' ||
            (use_tls && (*tls_certname == NULL || **tls_certname == '\0')))
    {
        char *msg;
        purple_debug_error("oscar", "startOSCARSession response was missing "
                           "something: %s\n", response);
        msg = generate_error_message(response_node,
                                     URL_START_OSCAR_SESSION);
        purple_connection_error_reason(gc,
                                       PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
        g_free(msg);
        g_free(*host);
        g_free(tmp);
        g_free(*cookie);
        xmlnode_free(response_node);
        return FALSE;
    }

    *port = atoi(tmp);
    g_free(tmp);

    return TRUE;
}
示例#4
0
static void fb_got_notifications_cb(FacebookAccount *fba, gchar *url_text, gsize len, gpointer userdata)
{
	gchar *salvaged;
	time_t last_fetch_time;
	time_t time_of_message;
	time_t newest_message = 0;
	xmlnode *channel;//VOXOX - CJC - 2009.07.06 
	xmlnode *rss_root;//VOXOX - CJC - 2009.07.06 
	xmlnode *item;//VOXOX - CJC - 2009.07.06 
	xmlnode *link;//VOXOX - CJC - 2009.07.06 
	xmlnode *title;//VOXOX - CJC - 2009.07.06 
	gchar *tmp;
	gchar month_string[4], weekday[4];
	guint year, month, day, hour, minute, second;
	long timezone;
	gchar *subject, *url;

	month_string[3] = weekday[3] = '\0';
	year = month = day = hour = minute = second = 0;

	if (!url_text || !len)
		return;

	last_fetch_time = purple_account_get_int(fba->account, "facebook_notifications_last_fetch", 0);
	/* purple_debug_info("facebook", "last fetch time: %zu\n", last_fetch_time); */

	salvaged = purple_utf8_salvage(url_text);
	rss_root = xmlnode_from_str(salvaged, -1);
	g_free(salvaged);

	if (rss_root == NULL)
	{
		purple_debug_error("facebook", "Could not load RSS file\n");
		return;
	}
	channel = xmlnode_get_child(rss_root, "channel");
	if (channel == NULL)
	{
		purple_debug_warning("facebook", "Invalid RSS feed\n");
		xmlnode_free(rss_root);
		return;
	}
	item = xmlnode_get_child(channel, "item");
	if (item == NULL)
	{
		purple_debug_info("facebook", "No new notifications\n");
	}
	for (; item != NULL; item = xmlnode_get_next_twin(item))
	{
		xmlnode *pubDate = xmlnode_get_child(item, "pubDate");
		if (!pubDate)
			continue;
		tmp = xmlnode_get_data_unescaped(pubDate);
		/* rss times are in Thu, 19 Jun 2008 15:51:25 -1100 format */
		sscanf(tmp, "%3s, %2u %3s %4u %2u:%2u:%2u %5ld", (char*)&weekday, &day, (char*)&month_string, &year, &hour, &minute, &second, &timezone);
		if (g_str_equal(month_string, "Jan")) month = 0;
		else if (g_str_equal(month_string, "Feb")) month = 1;
		else if (g_str_equal(month_string, "Mar")) month = 2;
		else if (g_str_equal(month_string, "Apr")) month = 3;
		else if (g_str_equal(month_string, "May")) month = 4;
		else if (g_str_equal(month_string, "Jun")) month = 5;
		else if (g_str_equal(month_string, "Jul")) month = 6;
		else if (g_str_equal(month_string, "Aug")) month = 7;
		else if (g_str_equal(month_string, "Sep")) month = 8;
		else if (g_str_equal(month_string, "Oct")) month = 9;
		else if (g_str_equal(month_string, "Nov")) month = 10;
		else if (g_str_equal(month_string, "Dec")) month = 11;
		g_free(tmp);

		/* try using pidgin's functions */
		tmp = g_strdup_printf("%04u%02u%02uT%02u%02u%02u%05ld", year, month, day, hour, minute, second, timezone);
		time_of_message = purple_str_to_time(tmp, FALSE, NULL, NULL, NULL);
		g_free(tmp);

		if (time_of_message <= 0)
		{
			/* there's no cross-platform, portable way of converting string to time
			   which doesn't need a new version of glib, so just cheat */
			time_of_message = second + 60*minute + 3600*hour + 86400*day + 2592000*month + 31536000*(year-1970);
		}

		if (time_of_message > newest_message)
		{
			/* we'll keep the newest message to save */
			newest_message = time_of_message;
		}

		if (time_of_message <= last_fetch_time)
		{
			/* fortunatly, rss messages are ordered from newest to oldest */
			/* so if this message is older than the last one, ignore rest */
			break;
		}
		
		link = xmlnode_get_child(item, "link");
		if (link)
		{
			url = xmlnode_get_data_unescaped(link);
		} else {
			url = g_strdup("");
		}
		
		title = xmlnode_get_child(item, "title");
		if (title)
		{
			subject = xmlnode_get_data_unescaped(title);
		} else {
			subject = g_strdup("");
		}
		
		purple_notify_email(fba->pc, subject, NULL, fba->account->username, url, NULL, NULL);
		g_free(subject);
		g_free(url);
	}
	xmlnode_free(rss_root);

	if (newest_message > last_fetch_time)
	{
		/* update the last fetched time if we had newer messages */
		purple_account_set_int(fba->account, "facebook_notifications_last_fetch", newest_message);
	}
}
示例#5
0
static gfire_game_detection_set *gfire_game_detection_set_create_from_xml(xmlnode *p_node)
{
	gfire_game_detection_set *ret = g_malloc0(sizeof(gfire_game_detection_set));

	gchar *tmp = NULL;

	// Enable server detection
	xmlnode *cur_node = xmlnode_get_child(p_node, "server_detection");
	if(cur_node)
	{
		tmp = xmlnode_get_data_unescaped(cur_node);
		if(tmp)
		{
			if(!g_utf8_collate(tmp, "enabled"))
				ret->detect_server = TRUE;
			g_free(tmp);
		}
	}

	// Excluded ports
	cur_node = xmlnode_get_child(p_node, "server_excluded_ports");
	if(cur_node)
	{
		tmp = xmlnode_get_data_unescaped(cur_node);
		if(tmp)
		{
			gchar **parray = g_strsplit(tmp, ";", -1);
			if(parray)
			{
				int i;
				for(i = 0; i < g_strv_length(parray); i++)
				{
					if(parray[i][0] == 0)
						continue;

					guint16 *port = g_malloc0(sizeof(guint16));
					sscanf(parray[i], "%hu", port);

					ret->excluded_ports = g_list_append(ret->excluded_ports, port);
				}
				g_strfreev(parray);
			}
			g_free(tmp);
		}
	}

	// Broadcast ports
	cur_node = xmlnode_get_child(p_node, "server_broadcast_ports");
	if(cur_node)
	{
		tmp = xmlnode_get_data_unescaped(cur_node);
		if(tmp)
		{
			gchar **parray = g_strsplit(tmp, ";", -1);
			if(parray)
			{
				int i;
				for(i = 0; i < g_strv_length(parray); i++)
				{
					if(parray[i][0] == 0)
						continue;

					ret->server_broadcast_ports = g_list_append(ret->server_broadcast_ports, g_strdup(parray[i]));
				}
				g_strfreev(parray);
			}
			g_free(tmp);
		}
	}

	// Server game name
	cur_node = xmlnode_get_child(p_node, "server_game_name");
	if(cur_node)
	{
		ret->server_game_name = xmlnode_get_data_unescaped(cur_node);
	}

	// Server status type
	cur_node = xmlnode_get_child(p_node, "server_status_type");
	if(cur_node)
	{
		ret->server_status_type = xmlnode_get_data_unescaped(cur_node);
	}

	// Launch PW args
	cur_node = xmlnode_get_child(p_node, "launch_password_args");
	if(cur_node)
	{
		ret->password_args = xmlnode_get_data_unescaped(cur_node);
	}

	// Launch network args
	cur_node = xmlnode_get_child(p_node, "launch_network_args");
	if(cur_node)
	{
		ret->network_args = xmlnode_get_data_unescaped(cur_node);
	}

	// Launch args
	cur_node = xmlnode_get_child(p_node, "launch_args");
	if(cur_node)
	{
		ret->launch_args = xmlnode_get_data_unescaped(cur_node);
	}

	// Arguments
	cur_node = xmlnode_get_child(p_node, "arguments");
	if(cur_node)
	{
		// Invalid args
		if(xmlnode_get_attrib(cur_node, "invalid"))
		{
			gchar **args = g_strsplit(xmlnode_get_attrib(cur_node, "invalid"), ";", -1);
			if(args)
			{
				int i;
				for(i = 0; i < g_strv_length(args); i++)
				{
					if(args[i][0] == 0)
						continue;

					ret->invalid_args = g_list_append(ret->invalid_args, g_strdup(args[i]));
				}

				g_strfreev(args);
			}
		}

		// Required args
		if(xmlnode_get_attrib(cur_node, "required"))
		{
			gchar **args = g_strsplit(xmlnode_get_attrib(cur_node, "required"), ";", -1);
			if(args)
			{
				int i;
				for(i = 0; i < g_strv_length(args); i++)
				{
					if(args[i][0] == 0)
						continue;

					ret->required_args = g_list_append(ret->required_args, g_strdup(args[i]));
				}

				g_strfreev(args);
			}
		}
	}

	// External
	cur_node = xmlnode_get_child(p_node, "external");
	if(cur_node)
	{
		ret->external = TRUE;

		// Detection URL
		if(xmlnode_get_attrib(cur_node, "url"))
		{
			ret->detect_url = g_strdup(xmlnode_get_attrib(cur_node, "url"));
		}

		// Launch URL
		if(xmlnode_get_attrib(cur_node, "launchurl"))
		{
			ret->launch_url = g_strdup(xmlnode_get_attrib(cur_node, "launchurl"));
		}
	}

	return ret;
}
示例#6
0
文件: fbapi.c 项目: hellais/Adium-old
static void purple_fbapi_request_fetch_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
{
	PurpleFbApiCall *apicall;
	xmlnode *response;
	PurpleConnectionError error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
	char *error_message2 = NULL;

	apicall = user_data;

	if (error_message != NULL) {
		/* Request failed */

		if (apicall->attempt_number < MAX_CONNECTION_ATTEMPTS) {
			/* Retry! */
			apicall->url_data = purple_util_fetch_url_request(API_URL,
					TRUE, NULL, FALSE, apicall->request, FALSE,
					purple_fbapi_request_fetch_cb, apicall);
			apicall->attempt_number++;
			return;
		}

		response = NULL;
		error_message2 = g_strdup(error_message);
		error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
	} else if (url_text != NULL && len > 0) {
		/* Parse the response as XML */
		response = xmlnode_from_str(url_text, len);

		if (response == NULL)
		{
			gchar *salvaged;

			if (g_utf8_validate(url_text, len, NULL)) {
				salvaged = g_strdup(url_text);
			} else {
				/* Facebook responded with invalid UTF-8.  Bastards. */
				purple_debug_error("fbapi", "Response is not valid UTF-8\n");
				salvaged = purple_utf8_salvage(url_text);
			}

			purple_fbapi_xml_salvage(salvaged);
			response = xmlnode_from_str(salvaged, -1);
			g_free(salvaged);
		}

		if (response == NULL) {
			purple_debug_error("fbapi", "Could not parse response as XML: %*s\n",
			(int)len, url_text);
			error_message2 = g_strdup(_("Invalid response from server"));
		} else if (g_str_equal(response->name, "error_response")) {
			/*
			 * The response is an error message, in the standard format
			 * for errors from API calls.
			 */
			xmlnode *tmp;
			char *tmpstr;

			tmp = xmlnode_get_child(response, "error_code");
			if (tmp != NULL) {
				tmpstr = xmlnode_get_data_unescaped(tmp);
				if (tmpstr != NULL && strcmp(tmpstr, "293") == 0) {
					error_message2 = g_strdup(_("Need chat permission"));
					error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
				}
				g_free(tmpstr);
			}
			if (error_message2 == NULL) {
				error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
				tmp = xmlnode_get_child(response, "error_msg");
				if (tmp != NULL)
					error_message2 = xmlnode_get_data_unescaped(tmp);
			}
			if (error_message2 == NULL)
				error_message2 = g_strdup(_("Unknown"));
		} else {
			error_message2 = NULL;
		}
	} else {
		/* Response body was empty */
		response = NULL;
		error_message2 = NULL;
	}

	if (apicall->attempt_number > 1 || error_message2 != NULL)
		purple_debug_error("fbapi", "Request '%s' %s after %u attempts: %s\n",
				apicall->request,
				error_message == NULL ? "succeeded" : "failed",
				apicall->attempt_number, error_message2);

	/*
	 * The request either succeeded or failed the maximum number of
	 * times.  In either case, pass control off to the callback
	 * function and let them decide what to do.
	 */
	apicall->callback(apicall, apicall->user_data, response, error, error_message2);
	apicall->url_data = NULL;
	purple_fbapi_request_destroy(apicall);

	xmlnode_free(response);
	g_free(error_message2);
}