コード例 #1
0
ファイル: gda-web-util.c プロジェクト: arthurnn/libgda
/**
 * _gda_web_set_connection_error_from_xmldoc
 *
 * Handles errors reported by @doc, and ser @error if not %NULL
 *
 * Returns: a #GdaConnectionEvent, which must not be modified or freed
 */
GdaConnectionEvent *
_gda_web_set_connection_error_from_xmldoc (GdaConnection *cnc, xmlDocPtr doc, GError **error)
{
	xmlNodePtr node, root;
	GdaConnectionEvent *ev = NULL;

	g_return_val_if_fail (doc, NULL);

	root = xmlDocGetRootElement (doc);
	for (node = root->children; node; node = node->next) {
		if (!strcmp ((gchar*) node->name, "status")) {
			xmlChar *prop;
			prop = xmlGetProp (node, BAD_CAST "error");
			if (prop) {
				ev = gda_connection_add_event_string (cnc, (gchar*) prop);
				xmlFree (prop);
			}
			else
				ev = gda_connection_add_event_string (cnc, _("Non detailed error"));
			break;
		}
	}

	if (ev && error) {
		g_set_error (error, GDA_SERVER_PROVIDER_ERROR,
			     GDA_SERVER_PROVIDER_STATEMENT_EXEC_ERROR, "%s",
			     gda_connection_event_get_description (ev));
	}

	return ev;
}
コード例 #2
0
ファイル: gda-oracle-util.c プロジェクト: UIKit0/libgda
/* 
 * _gda_oracle_handle_error
 * This function is used for checking the result of an OCI
 * call.  The result itself is the return value, and we
 * need the GdaConnection and OracleConnectionData to do
 * our thing.  The type is OCI_HTYPE_ENV or OCI_HTYPE_ERROR
 * as described for OCIErrorGet.
 *
 * The return value is true if there is no error, or false otherwise
 *
 * If the return value is OCI_SUCCESS or OCI_SUCCESS_WITH_INFO,
 * we return TRUE.  Otherwise, if it is OCI_ERROR, try to get the
 * Oracle error message using _gda_oracle_make_error.  Otherwise,
 * make an error using the given message.
 */
GdaConnectionEvent * 
_gda_oracle_handle_error (gint result, GdaConnection *cnc, 
			  OracleConnectionData *cdata,
			  ub4 type, const gchar *msg,
			  const gchar *file, gint line)
{
	GdaConnectionEvent *error = NULL;
	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);

	switch (result) {
	case OCI_SUCCESS:
	case OCI_SUCCESS_WITH_INFO:
		return NULL;
	case OCI_ERROR:
		switch(type) {
		case OCI_HTYPE_ERROR:
			error = _gda_oracle_make_error (cnc, cdata->herr, type, file, line);
			gda_connection_add_event (cnc, error);
			break;
		case OCI_HTYPE_ENV:
			error = _gda_oracle_make_error (cnc, cdata->henv, type, file, line);
			if (error)
				gda_connection_add_event (cnc, error);
			break;
		default:
			if (error)
				error = gda_connection_add_event_string (cnc, msg);
			gda_connection_add_event (cnc, error);
			break;
		}
		break;
	case OCI_NO_DATA:
		g_warning ("Internal implementation error: OCI_NO_DATA not handled!\n");
		break;
	case OCI_INVALID_HANDLE:
		g_warning ("Internal error: Invalid handle!");
	default:
		error = gda_connection_add_event_string (cnc, msg);
	}

#ifdef GDA_DEBUG
	if (error)
		g_print ("HANDLED error: %s\n", gda_connection_event_get_description (error));
#endif
	return error;
}
コード例 #3
0
ファイル: gda-web-util.c プロジェクト: arthurnn/libgda
static void
start_worker (GdaConnection *cnc, WebConnectionData *cdata)
{
	ThreadData *thdata;

	thdata = g_new0 (ThreadData, 1); /* freed by sub thread */
	thdata->cnc = cnc;
	thdata->cdata = cdata;

	/* set cdata->worker_running to TRUE to avoid having to add a delay */
	g_rec_mutex_lock (& (cdata->mutex));
	cdata->worker_running = TRUE;
	g_rec_mutex_unlock (& (cdata->mutex));

	if (! g_thread_new ("web-worker", (GThreadFunc) start_worker_in_sub_thread,
			    thdata)) {
		g_free (thdata);
		gda_connection_add_event_string (cnc, _("Can't start new thread"));
		return;
	}
	
	gint nb_retries;
	for (nb_retries = 0; nb_retries < 10; nb_retries++) {
		gboolean wait_over;
		g_rec_mutex_lock (& (cdata->mutex));
		wait_over = !cdata->worker_running || cdata->session_id;
		g_rec_mutex_unlock (& (cdata->mutex));
		if (wait_over)
			break;
		else
			g_usleep (200000);
	}

	g_rec_mutex_lock (& (cdata->mutex));
	if (!cdata->session_id) {
		/* there was an error */
		cdata->worker_running = FALSE;
	}
	g_rec_mutex_unlock (& (cdata->mutex));
}
コード例 #4
0
ファイル: gda-web-util.c プロジェクト: arthurnn/libgda
/*
 * Cleans any remaining data on the web server
 */
void
_gda_web_do_server_cleanup (GdaConnection *cnc, WebConnectionData *cdata)
{
	SoupMessage *msg;
	guint status;
	gchar *real_url;
	gint nb_retries;

	/* wait for worker to finish */
	g_rec_mutex_lock (& (cdata->mutex));
	for (nb_retries = 0; (nb_retries < 10) && cdata->worker_running; nb_retries ++) {
		g_rec_mutex_unlock (& (cdata->mutex));
		g_usleep (50000);
		g_rec_mutex_lock (& (cdata->mutex));
	}
	g_rec_mutex_unlock (& (cdata->mutex));
 
	real_url = g_strdup_printf ("%s/gda-clean.php?%s", cdata->server_base_url, cdata->session_id);
	msg = soup_message_new ("GET", real_url);
	if (!msg) {
		gda_connection_add_event_string (cnc, _("Invalid HOST/SCRIPT '%s'"), real_url);
 		g_free (real_url);
		return;
 	}
	g_free (real_url);

	g_object_set (G_OBJECT (cdata->front_session), SOUP_SESSION_TIMEOUT, 5, NULL);
	status = soup_session_send_message (cdata->front_session, msg);
	g_object_unref (msg);

	if (!SOUP_STATUS_IS_SUCCESSFUL (status))
		g_warning (_("Error cleaning data on the server for session %s"), cdata->session_id);
#ifdef DEBUG_WEB_PROV
	else
		g_print ("CLEANUP DONE!\n");
#endif
}
コード例 #5
0
ファイル: gda-web-util.c プロジェクト: arthurnn/libgda
/*
 * If there is a mismatch or an error, then gda_connection_add_event_string() is used
 *
 *  - Modifies @sbuffer (to separate HASH from XML part)
 *  - if all OK, extracs the <challenge> value and replace cdata->next_challenge with it (or simply
 *    reset cdata->next_challenge to NULL)
 *
 * Returns: a new #xmlDocPtr, or %NULL on error
 */
static xmlDocPtr
decode_buffer_response (GdaConnection *cnc, WebConnectionData *cdata, SoupBuffer *sbuffer,
			gchar *out_status_chr, guint *out_counter_id)
{
	xmlDocPtr doc;
	gchar *ptr, *response;

	if (out_status_chr)
		*out_status_chr = 0;
	if (out_counter_id)
		*out_counter_id = 0;

	g_assert (sbuffer);
	response = (gchar*) sbuffer->data;

	for (ptr = response; *ptr && (*ptr != '\n'); ptr++);
	if (*ptr != '\n') {
		gda_connection_add_event_string (cnc, _("Could not parse server's reponse"));
		return NULL;
	}
	*ptr = 0;
	ptr++;

	if ((cdata->key && !check_hash (cdata->key, ptr, response)) &&
	    (cdata->server_secret && !check_hash (cdata->server_secret, ptr, response))) {
		gda_connection_add_event_string (cnc, _("Invalid response hash"));
		return NULL;
	}
	doc = xmlParseMemory (ptr, strlen (ptr));

	if (!doc) {
		gda_connection_add_event_string (cnc, _("Could not parse server's reponse"));
		return NULL;
	}
	else {
		xmlNodePtr node, root;

		root = xmlDocGetRootElement (doc);
		for (node = root->children; node; node = node->next) {
			if (!strcmp ((gchar*) node->name, "session")) {
				xmlChar *contents;
				contents = xmlNodeGetContent (node);
				g_free (cdata->session_id);
				cdata->session_id = g_strdup ((gchar*) contents);
				xmlFree (contents);
			}
			else if (!strcmp ((gchar*) node->name, "challenge")) {
				xmlChar *contents;
				if (cdata->next_challenge) {
					g_free (cdata->next_challenge);
					cdata->next_challenge = NULL;
				}
				contents = xmlNodeGetContent (node);
				cdata->next_challenge = g_strdup ((gchar*) contents);
				xmlFree (contents);
			}
			else if (out_status_chr && !strcmp ((gchar*) node->name, "status")) {
				xmlChar *contents;
				contents = xmlNodeGetContent (node);
				*out_status_chr = *contents;
				xmlFree (contents);
			}
			else if (out_counter_id && !strcmp ((gchar*) node->name, "counter")) {
				xmlChar *contents;
				contents = xmlNodeGetContent (node);
				*out_counter_id = atoi ((gchar*) contents);
				xmlFree (contents);
			}
			else if (!cdata->server_id && !strcmp ((gchar*) node->name, "servertype")) {
				xmlChar *contents;
				contents = xmlNodeGetContent (node);
				cdata->server_id = g_strdup ((gchar*) contents);
				xmlFree (contents);

				cdata->reuseable = _gda_provider_reuseable_new (cdata->server_id);
#ifdef DEBUG_WEB_PROV
				g_print ("REUSEABLE [%s]: %p\n", cdata->server_id, cdata->reuseable);
#endif
			}
			else if (!cdata->server_version && !strcmp ((gchar*) node->name, "serverversion")) {
				xmlChar *contents;
				contents = xmlNodeGetContent (node);
				cdata->server_version = g_strdup ((gchar*) contents);
				xmlFree (contents);
#ifdef DEBUG_WEB_PROV
				g_print ("SERVER version [%s]\n", cdata->server_version);
#endif
			}
		}
	}

	return doc;
}
コード例 #6
0
ファイル: gda-web-util.c プロジェクト: arthurnn/libgda
/*
 * Adds a HASH to the message using @hash_key, or adds "NOHASH" if @hash_key is %NULL
 *
 * If there is an error, then gda_connection_add_event_string() is called
 *
 * @out_status_chr, if NOT NULL will contain the 1st char of the <status> node's contents
 */
xmlDocPtr
_gda_web_send_message_to_frontend (GdaConnection *cnc, WebConnectionData *cdata,
				   WebMessageType msgtype, const gchar *message,
				   const gchar *hash_key, gchar *out_status_chr)
{
	SoupMessage *msg;
	guint status;
	gchar *h_message;
	gchar *real_url;
	static gint counter = 0;

	if (out_status_chr)
		*out_status_chr = 0;

	/* handle the need to run the worker to get an initial sessionID */
	g_rec_mutex_lock (& (cdata->mutex));
	cdata->worker_needed = TRUE;
	if (!cdata->worker_running && !cdata->session_id) {
		g_rec_mutex_unlock (& (cdata->mutex));
		start_worker (cnc, cdata);

		g_rec_mutex_lock (& (cdata->mutex));
		if (! cdata->worker_running) {
			gda_connection_add_event_string (cnc, _("Could not run PHP script on the server"));
			cdata->worker_needed = FALSE;
			g_rec_mutex_unlock (& (cdata->mutex));
			return NULL;
		}
	}

	/* prepare new message */
	g_assert (cdata->session_id);
	real_url = g_strdup_printf ("%s?%s&c=%d", cdata->front_url, cdata->session_id, counter++);
	g_rec_mutex_unlock (& (cdata->mutex));
	msg = soup_message_new ("POST", real_url);
	if (!msg) {
		gda_connection_add_event_string (cnc, _("Invalid HOST/SCRIPT '%s'"), real_url);
		g_free (real_url);
		return NULL;
	}
	g_free (real_url);

	/* check context */
	g_rec_mutex_lock (& (cdata->mutex));
	if (gda_connection_get_transaction_status (cnc) &&
	    (!cdata->worker_running ||
	     ((msgtype == MESSAGE_EXEC) && (cdata->last_exec_counter != cdata->worker_counter)))) {
		/* update cdata->last_exec_counter so next statement can be run */
		cdata->last_exec_counter = cdata->worker_counter;

		gda_connection_add_event_string (cnc, _("The transaction has been automatically rolled back"));
		g_object_unref (msg);

		gda_connection_internal_reset_transaction_status (cnc);
		g_rec_mutex_unlock (& (cdata->mutex));
		return NULL;
	}
	if (! cdata->worker_running) {
		g_rec_mutex_unlock (& (cdata->mutex));
		start_worker (cnc, cdata);

		g_rec_mutex_lock (& (cdata->mutex));
		if (! cdata->worker_running) {
			gda_connection_add_event_string (cnc, _("Could not run PHP script on the server"));
			g_object_unref (msg);
			g_rec_mutex_unlock (& (cdata->mutex));
			return NULL;
		}
	}
	g_rec_mutex_unlock (& (cdata->mutex));

	/* finalize and send message */
 	if (hash_key) {
		gchar *md5str;
		md5str = g_compute_hmac_for_string (G_CHECKSUM_MD5, hash_key, strlen (hash_key),
						    message, -1);

		GString *string;
		string = g_string_new (md5str);
		g_free (md5str);
		g_string_append_c (string, '\n');
		g_string_append (string, message);
		h_message = g_string_free (string, FALSE);
	}
	else
		h_message = g_strdup_printf ("NOHASH\n%s", message);
	
#ifdef DEBUG_WEB_PROV
	g_print ("=== START of request ===\n%s\n=== END of request ===\n", h_message);
#endif
	soup_message_set_request (msg, "text/plain",
				  SOUP_MEMORY_COPY, h_message, strlen (h_message));
	g_free (h_message);
	g_object_set (G_OBJECT (cdata->front_session), SOUP_SESSION_TIMEOUT, 20, NULL);
	status = soup_session_send_message (cdata->front_session, msg);

	g_rec_mutex_lock (& (cdata->mutex));
	cdata->worker_needed = FALSE;
	g_rec_mutex_unlock (& (cdata->mutex));

	if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
		gda_connection_add_event_string (cnc, msg->reason_phrase);
		g_object_unref (msg);
		return NULL;
	}

	xmlDocPtr doc;
	guint counter_id;
	doc = _gda_web_decode_response (cnc, cdata, msg->response_body, out_status_chr, &counter_id);
	g_object_unref (msg);
	
	g_rec_mutex_lock (& (cdata->mutex));
	if (msgtype == MESSAGE_EXEC)
		cdata->last_exec_counter = counter_id;
	g_rec_mutex_unlock (& (cdata->mutex));

	return doc;
}
コード例 #7
0
ファイル: gda-oracle-util.c プロジェクト: UIKit0/libgda
void
_gda_oracle_set_value (GValue *value, 
		       GdaOracleValue *ora_value,
		       GdaConnection *cnc)
{
	GdaTime gtime;
	GdaTimestamp timestamp;
	sb2 year;
	ub1 month;
	ub1 day;
	ub1 hour;
	ub1 min;
	ub1 sec;

	if (ora_value->indicator == -1) {
		gda_value_set_null (value);
		return;
	}

	gda_value_reset_with_type (value, ora_value->g_type);
	switch (ora_value->s_type) {
	case GDA_STYPE_INT:
		g_value_set_int (value, *((gint *) ora_value->value));
		break;
	case GDA_STYPE_STRING: {
		gchar *string_buffer, *tmp;
		
		string_buffer = (gchar *) ora_value->value;
		string_buffer [ora_value->rlen] = '\0';
		g_strchomp (string_buffer);
		//tmp = g_locale_to_utf8 (string_buffer, -1, NULL, NULL, NULL);
		//g_value_take_string (value, tmp);
		g_value_set_string (value, string_buffer);
		if (ora_value->use_callback) {
			g_free (string_buffer);
			ora_value->value = NULL;
		}
		break;
	}
	case GDA_STYPE_BOOLEAN:
		g_value_set_boolean (value, (*((gint *) ora_value->value)) ? TRUE: FALSE);
		break;
	case GDA_STYPE_DATE: {
		GDate *date;
		OCIDateGetDate ((CONST OCIDate *) ora_value->value,
				(sb2 *) &year,
				(ub1 *) &month,
				(ub1 *) &day);
		date = g_date_new_dmy (day, month, year);
		g_value_take_boxed (value, date);
		break;
	}
	case GDA_STYPE_TIME: {
		OCIDateGetTime ((CONST OCIDate *) ora_value->value,
				(ub1 *) &hour,
				(ub1 *) &min,
				(ub1 *) &sec);
		gtime.hour = hour;
		gtime.minute = min;
		gtime.second = sec;
		gda_value_set_time (value, &gtime);
		break;
	}
	case GDA_STYPE_TIMESTAMP: {
		OCIDateGetDate ((CONST OCIDate *) ora_value->value,
				(sb2 *) &year,
				(ub1 *) &month,
				(ub1 *) &day);
		OCIDateGetTime ((CONST OCIDate *) ora_value->value,
				(ub1 *) &hour,
				(ub1 *) &min,
				(ub1 *) &sec);
		timestamp.year = year;
		timestamp.month = month;
		timestamp.day = day;
		timestamp.hour = hour;
		timestamp.minute = min;
		timestamp.second = sec;
		timestamp.fraction = 0;
		timestamp.timezone = 0;
		gda_value_set_timestamp(value, &timestamp);
		break;
	}
	case GDA_STYPE_INT64:
		TO_IMPLEMENT; /* test that value fits in */
		g_value_set_int64 (value, atoll (ora_value->value));
		break;
	case GDA_STYPE_UINT64:
		TO_IMPLEMENT; /* test that value fits in */
		g_value_set_uint64 (value, atoll (ora_value->value));
		break;
	case GDA_STYPE_UINT:
		TO_IMPLEMENT; /* test that value fits in */
		g_value_set_uint (value, *((guint*) ora_value->value));
		break;
	case GDA_STYPE_FLOAT:
		g_value_set_float (value, *((gfloat*) ora_value->value));
		break;
	case GDA_STYPE_DOUBLE:
		g_value_set_double (value, *((gdouble*) ora_value->value));
		break;
	case GDA_STYPE_LONG:
		TO_IMPLEMENT;
		break;
	case GDA_STYPE_ULONG:
		TO_IMPLEMENT;
		break;
	case GDA_STYPE_NUMERIC: {
		GdaNumeric *numeric;
		gchar *tmp;
		g_assert (!ora_value->use_callback);
		
		tmp = g_malloc0 (ora_value->defined_size);
		memcpy (tmp, ora_value->value, ora_value->defined_size);
		tmp [ora_value->rlen] = '\0';
		g_strchomp (tmp);

		numeric = gda_numeric_new ();
		gda_numeric_set_from_string (numeric, tmp);
		g_free (tmp);
		gda_numeric_set_precision (numeric, ora_value->precision);
		gda_numeric_set_width (numeric, ora_value->scale);
		g_value_take_boxed (value, numeric);
		break;
	}
	case GDA_STYPE_BINARY: {
		GdaBinary *bin;

		bin = g_new0 (GdaBinary, 1);
		if (ora_value->use_callback) {		
			bin->data = ora_value->value;
			ora_value->value = NULL;
		}
		else {
			bin->data = g_new (guchar, ora_value->rlen);
			memcpy (bin->data, ora_value->value, ora_value->rlen);
		}
		bin->binary_length = ora_value->rlen;
		gda_value_take_binary (value, bin);
		break;
	}
	case GDA_STYPE_BLOB: {
		GdaBlob *blob;
		GdaBlobOp *op;
		OCILobLocator *lobloc;
		OracleConnectionData *cdata;
		gint result;

		/* REM: we need to make a "copy" of the lob locator to give to the GdaOracleblobOp object */
		cdata = (OracleConnectionData*) gda_connection_internal_get_provider_data_error (cnc, NULL);
		if (!cdata) {
			gda_connection_add_event_string (cnc, _("Invalid Oracle handle"));
			gda_value_set_null (value);
			return;
		}

		result = OCIDescriptorAlloc ((dvoid *) cdata->henv, (dvoid **) &lobloc, 
					     (ub4) gda_oracle_blob_type (ora_value->sql_type), (size_t) 0, (dvoid **) 0);
		if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
					     _("Could not allocate Lob locator"))) {
			gda_value_set_null (value);
			return;
		}

		result = OCILobAssign ((dvoid *) cdata->henv, (dvoid *) cdata->herr, ora_value->value, &lobloc);
		if (gda_oracle_check_result (result, cnc, cdata, OCI_HTYPE_ERROR,
					     _("Could not copy Lob locator"))) {
			gda_value_set_null (value);
			return;
		}

		blob = g_new0 (GdaBlob, 1);
		op = gda_oracle_blob_op_new (cnc, lobloc);
		gda_blob_set_op (blob, op);
		g_object_unref (op);

		gda_value_take_blob (value, blob);
		break;
	}
	case GDA_STYPE_CHAR: {
		TO_IMPLEMENT; /* test that value fits in */
		g_value_set_schar (value, *((gint8*) ora_value->value));
		break;
	}
	case GDA_STYPE_SHORT: {
		TO_IMPLEMENT; /* test that value fits in */
		gda_value_set_short (value, *((gint*) ora_value->value));
		break;
	}
	case GDA_STYPE_GTYPE:
		TO_IMPLEMENT;
		break;
	case GDA_STYPE_GEOMETRIC_POINT:
		TO_IMPLEMENT;
		break;
	case GDA_STYPE_NULL:
		gda_value_set_null (value);
		break;
	default:
		g_assert_not_reached ();
	}
}
コード例 #8
0
ファイル: gda-ldap-provider.c プロジェクト: arthurnn/libgda
/* 
 * Prepare connection request
 *
 * In this function, the following _must_ be done:
 *   - check for the presence and validify of the parameters required to actually open a connection,
 *     using @params
 *   - open the real connection to the database using the parameters previously checked, create one or
 *     more GdaDataModel objects and declare them to the virtual connection with table names
 *   - create a LdapConnectionData structure and associate it to @cnc
 *
 * Returns: TRUE if no error occurred, or FALSE otherwise (and an ERROR connection event must be added to @cnc)
 */
static gboolean
gda_ldap_provider_prepare_connection (GdaServerProvider *provider, GdaConnection *cnc,
				      GdaQuarkList *params, GdaQuarkList *auth)
{
	g_return_val_if_fail (GDA_IS_LDAP_PROVIDER (provider), FALSE);
	g_return_val_if_fail (GDA_IS_CONNECTION (cnc), FALSE);

	/* Check for connection parameters */
	const gchar *base_dn;
	const gchar *host;
	const gchar *tmp;
	const gchar *port;
	const gchar *user = NULL;
	gchar *dnuser = NULL;
        const gchar *pwd = NULL;
        const gchar *time_limit = NULL;
        const gchar *size_limit = NULL;
        const gchar *tls_method = NULL;
        const gchar *tls_cacert = NULL;
	int rtls_method = -1;
	gint rport;
	gboolean use_ssl, use_cache;

	/* calling the parent's function first */
	GdaServerProviderBase *parent_functions;
        parent_functions = gda_server_provider_get_impl_functions_for_class (parent_class, GDA_SERVER_PROVIDER_FUNCTIONS_BASE);
	if (parent_functions->prepare_connection) {
		if (! parent_functions->prepare_connection (GDA_SERVER_PROVIDER (provider), cnc, params, auth))
			return FALSE;
	}

        base_dn = gda_quark_list_find (params, "DB_NAME");
        if (!base_dn) {
                gda_connection_add_event_string (cnc, "%s",
                                                 _("The connection string must contain the DB_NAME value"));
                return FALSE;
        }
	host = gda_quark_list_find (params, "HOST");
	if (!host)
		host = "127.0.0.1";
        port = gda_quark_list_find (params, "PORT");
        tmp = gda_quark_list_find (params, "USE_SSL");
	use_ssl = (tmp && ((*tmp == 't') || (*tmp == 'T'))) ? TRUE : FALSE;
	tmp = gda_quark_list_find (params, "USE_CACHE");
	use_cache = (!tmp || ((*tmp == 't') || (*tmp == 'T'))) ? TRUE : FALSE;
	if (port && *port)
		rport = atoi (port);
	else {
		if (use_ssl)
			rport = LDAPS_PORT;
		else
			rport = LDAP_PORT;
	}
	user = gda_quark_list_find (auth, "USERNAME");
        if (!user)
                user = gda_quark_list_find (params, "USERNAME");
        pwd = gda_quark_list_find (auth, "PASSWORD");
        if (!pwd)
                pwd = gda_quark_list_find (params, "PASSWORD");

	tls_cacert = gda_quark_list_find (params, "TLS_CACERT");
	tls_method = gda_quark_list_find (params, "TLS_REQCERT");
	if (tls_method && *tls_method) {
		if (! g_ascii_strcasecmp (tls_method, "never"))
			rtls_method = LDAP_OPT_X_TLS_NEVER;
		else if (! g_ascii_strcasecmp (tls_method, "hard"))
			rtls_method = LDAP_OPT_X_TLS_HARD;
		else if (! g_ascii_strcasecmp (tls_method, "demand"))
			rtls_method = LDAP_OPT_X_TLS_DEMAND;
		else if (! g_ascii_strcasecmp (tls_method, "allow"))
			rtls_method = LDAP_OPT_X_TLS_ALLOW;
		else if (! g_ascii_strcasecmp (tls_method, "try"))
			rtls_method = LDAP_OPT_X_TLS_TRY;
		else {
			gda_connection_add_event_string (cnc, "%s",
							 _("Invalid value for 'TLS_REQCERT'"));
			return FALSE;
		}
	}
	time_limit = gda_quark_list_find (params, "TIME_LIMIT");
	size_limit = gda_quark_list_find (params, "SIZE_LIMIT");

	/* open LDAP connection */
	LdapConnectionData *cdata;
	LDAP *ld;
        int res;
	gchar *url;

	if (use_ssl) {
		/* Configuring SSL/TLS options:
		 * this is for texting purpose only, and should actually be done through LDAP's conf.
		 * files, see: man 5 ldap.conf
		 *
		 * For example ~/.ldaprc can contain:
		 * TLS_REQCERT demand
		 * TLS_CACERT /usr/share/ca-certificates/mozilla/Thawte_Premium_Server_CA.crt
		 *
		 * Note: if server certificate verification fails,
		 * the error message is: "Can't contact LDAP server"
		 */
		if (rtls_method >= 0) {
			res = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &rtls_method);
			if (res != LDAP_SUCCESS) {
				gda_connection_add_event_string (cnc, ldap_err2string (res));
				return FALSE;
			}
		}

		if (tls_cacert && *tls_cacert) {
			res = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, tls_cacert);
			if (res != LDAP_SUCCESS) {
				gda_connection_add_event_string (cnc, ldap_err2string (res));
				return FALSE;
			}
		}

		url = g_strdup_printf ("ldaps://%s:%d", host, rport);
	}
	else
		url = g_strdup_printf ("ldap://%s:%d", host, rport);

	if (user && *user && ! gda_ldap_parse_dn (user, NULL)) {
		/* analysing the @user parameter */
		/* the user name is not a DN => we need to fetch the DN of the entry
		 * using filters defined in the "mappings" array @user */
		guint i;
		const gchar *ptr;
		GString *rname;
		rname = g_string_new ("");
		for (ptr = user; *ptr; ptr++) {
			if ((*ptr == ',') || (*ptr == '\\') || (*ptr == '#') ||
			    (*ptr == '+') || (*ptr == '<') ||
			    (*ptr == '>') || (*ptr == ';') || (*ptr == '"') ||
			    (*ptr == '=') || (*ptr == '*'))
				g_string_append_c (rname, '\\');
			g_string_append_c (rname, *ptr);
		}
		for (i = 0; i < sizeof (mappings) / sizeof (LdapAuthMapping); i++) {
			gchar *tmp;
			tmp = fetch_user_dn (url, base_dn, rname->str, &(mappings[i]));
			if (tmp) {
				dnuser = tmp;
				break;
			}
		}
		g_string_free (rname, TRUE);

		/* if no DN user has been found, then still use the provided name AS IS
		 * => dnuser can be %NULL here */
	}

	res = ldap_initialize (&ld, url);
        if (res != LDAP_SUCCESS) {
		gda_connection_add_event_string (cnc, ldap_err2string (res));
		g_free (url);
		g_free (dnuser);
                return FALSE;
        }

	cdata = g_new0 (LdapConnectionData, 1);
	cdata->keep_bound_count = 0;
	cdata->handle = ld;
	cdata->url = url;
	cdata->time_limit = 0;
	cdata->size_limit = 0;
	cdata->base_dn = g_strdup (base_dn);
	if (use_cache)
		cdata->attributes_cache_file = compute_data_file_name (params, TRUE, "attrs");

	/* set protocol version to 3 by default */
	int version = LDAP_VERSION3;
	res = ldap_set_option (cdata->handle, LDAP_OPT_PROTOCOL_VERSION, &version);
        if (res != LDAP_SUCCESS) {
		if (res == LDAP_PROTOCOL_ERROR) {
			version = LDAP_VERSION2;
			res = ldap_set_option (cdata->handle, LDAP_OPT_PROTOCOL_VERSION, &version);
		}
		if (res != LDAP_SUCCESS) {
			gda_connection_add_event_string (cnc, ldap_err2string (res));
			gda_ldap_free_cnc_data (cdata);
			g_free (dnuser);
			return FALSE;
		}
        }

	/* time limit */
	if (time_limit && *time_limit) {
		int limit = atoi (time_limit);
		res = ldap_set_option (cdata->handle, LDAP_OPT_TIMELIMIT, &limit);
		if (res != LDAP_SUCCESS) {
			gda_connection_add_event_string (cnc, ldap_err2string (res));
			gda_ldap_free_cnc_data (cdata);
			g_free (dnuser);
			return FALSE;
		}
		cdata->time_limit = limit;
	}

	/* size limit */
	if (size_limit && *size_limit) {
		int limit = atoi (size_limit);
		res = ldap_set_option (cdata->handle, LDAP_OPT_SIZELIMIT, &limit);
		if (res != LDAP_SUCCESS) {
			gda_connection_add_event_string (cnc, ldap_err2string (res));
			gda_ldap_free_cnc_data (cdata);
			g_free (dnuser);
			return FALSE;
		}
		cdata->size_limit = limit;
	}

	/* authentication */
	struct berval cred;
        memset (&cred, 0, sizeof (cred));
        cred.bv_len = pwd && *pwd ? strlen (pwd) : 0;
        cred.bv_val = pwd && *pwd ? (char *) pwd : NULL;
        res = ldap_sasl_bind_s (ld, dnuser ? dnuser : user, NULL, &cred, NULL, NULL, NULL);
	if (res != LDAP_SUCCESS) {
		gda_connection_add_event_string (cnc, ldap_err2string (res));
		gda_ldap_free_cnc_data (cdata);
		g_free (dnuser);
                return FALSE;
	}
	if (pwd) {
		gchar *tmp;
		tmp = g_strdup_printf ("PASSWORD=%s", pwd);
		cdata->auth = gda_quark_list_new_from_string (tmp);
		g_free (tmp);
	}
	if (dnuser) {
		gchar *tmp;
		tmp = g_strdup_printf ("USERNAME=%s", dnuser);
		if (cdata->auth)
			gda_quark_list_add_from_string (cdata->auth, tmp, FALSE);
		else
			cdata->auth = gda_quark_list_new_from_string (tmp);
		g_free (tmp);
		dnuser = NULL;
	}
	else if (user) {
		gchar *tmp;
		tmp = g_strdup_printf ("USERNAME=%s", user);
		if (cdata->auth)
			gda_quark_list_add_from_string (cdata->auth, tmp, FALSE);
		else
			cdata->auth = gda_quark_list_new_from_string (tmp);
		g_free (tmp);
	}

	/* set startup file name */
	gchar *fname;
	fname = compute_data_file_name (params, FALSE, "start");
	g_object_set ((GObject*) cnc, "startup-file", fname, NULL);
	g_free (fname);

	/* open virtual connection */
	gda_virtual_connection_internal_set_provider_data (GDA_VIRTUAL_CONNECTION (cnc), 
							   cdata, (GDestroyNotify) gda_ldap_free_cnc_data);
	gda_ldap_may_unbind (GDA_LDAP_CONNECTION (cnc));
	return TRUE;
}