/** * _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; }
/* * _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; }
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)); }
/* * 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 }
/* * 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; }
/* * 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; }
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, >ime); 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, ×tamp); 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 (); } }
/* * 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; }