/* * Read the next line from a tsearch data file (expected to be in UTF-8), and * convert it to database encoding if needed. The returned string is palloc'd. * NULL return means EOF. * * Note: direct use of this function is now deprecated. Go through * tsearch_readline() to provide better error reporting. */ char * t_readline(FILE *fp) { int len; char *recoded; char buf[4096]; /* lines must not be longer than this */ if (fgets(buf, sizeof(buf), fp) == NULL) return NULL; len = strlen(buf); /* Make sure the input is valid UTF-8 */ (void) pg_verify_mbstr(PG_UTF8, buf, len, false); /* And convert */ recoded = pg_any_to_server(buf, len, PG_UTF8); if (recoded == buf) { /* * conversion didn't pstrdup, so we must. We can use the length of the * original string, because no conversion was done. */ recoded = pnstrdup(recoded, len); } return recoded; }
/* * Converts OpenSSL ASN1_STRING structure into text * * Converts ASN1_STRING into text, converting all the characters into * current database encoding if possible. Any invalid characters are * replaced by question marks. * * Parameter: str - OpenSSL ASN1_STRING structure. Memory management * of this structure is responsibility of caller. * * Returns Datum, which can be directly returned from a C language SQL * function. */ static Datum ASN1_STRING_to_text(ASN1_STRING *str) { BIO *membuf; size_t size; char nullterm; char *sp; char *dp; text *result; membuf = BIO_new(BIO_s_mem()); if (membuf == NULL) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("could not create OpenSSL BIO structure"))); (void) BIO_set_close(membuf, BIO_CLOSE); ASN1_STRING_print_ex(membuf, str, ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB) | ASN1_STRFLGS_UTF8_CONVERT)); /* ensure null termination of the BIO's content */ nullterm = '\0'; BIO_write(membuf, &nullterm, 1); size = BIO_get_mem_data(membuf, &sp); dp = pg_any_to_server(sp, size - 1, PG_UTF8); result = cstring_to_text(dp); if (dp != sp) pfree(dp); if (BIO_free(membuf) != 1) elog(ERROR, "could not free OpenSSL BIO structure"); PG_RETURN_TEXT_P(result); }
/* * Converts OpenSSL ASN1_STRING structure into text * * Converts ASN1_STRING into text, converting all the characters into * current database encoding if possible. Any invalid characters are * replaced by question marks. * * Parameter: str - OpenSSL ASN1_STRING structure. Memory management * of this structure is responsibility of caller. * * Returns Datum, which can be directly returned from a C language SQL * function. */ static Datum ASN1_STRING_to_text(ASN1_STRING *str) { BIO *membuf; size_t size; char nullterm; char *sp; char *dp; text *result; membuf = BIO_new(BIO_s_mem()); (void) BIO_set_close(membuf, BIO_CLOSE); ASN1_STRING_print_ex(membuf, str, ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB) | ASN1_STRFLGS_UTF8_CONVERT)); /* ensure null termination of the BIO's content */ nullterm = '\0'; BIO_write(membuf, &nullterm, 1); size = BIO_get_mem_data(membuf, &sp); dp = pg_any_to_server(sp, size - 1, PG_UTF8); result = cstring_to_text(dp); if (dp != sp) pfree(dp); BIO_free(membuf); PG_RETURN_TEXT_P(result); }
/* * Equivalent of X509_NAME_oneline that respects encoding * * This function converts X509_NAME structure to the text variable * converting all textual data into current database encoding. * * Parameter: X509_NAME *name X509_NAME structure to be converted * * Returns: text datum which contains string representation of * X509_NAME */ static Datum X509_NAME_to_text(X509_NAME *name) { BIO *membuf = BIO_new(BIO_s_mem()); int i, nid, count = X509_NAME_entry_count(name); X509_NAME_ENTRY *e; ASN1_STRING *v; const char *field_name; size_t size; char nullterm; char *sp; char *dp; text *result; if (membuf == NULL) ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("could not create OpenSSL BIO structure"))); (void) BIO_set_close(membuf, BIO_CLOSE); for (i = 0; i < count; i++) { e = X509_NAME_get_entry(name, i); nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e)); if (nid == NID_undef) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not get NID for ASN1_OBJECT object"))); v = X509_NAME_ENTRY_get_data(e); field_name = OBJ_nid2sn(nid); if (field_name == NULL) field_name = OBJ_nid2ln(nid); if (field_name == NULL) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("could not convert NID %d to an ASN1_OBJECT structure", nid))); BIO_printf(membuf, "/%s=", field_name); ASN1_STRING_print_ex(membuf, v, ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB) | ASN1_STRFLGS_UTF8_CONVERT)); } /* ensure null termination of the BIO's content */ nullterm = '\0'; BIO_write(membuf, &nullterm, 1); size = BIO_get_mem_data(membuf, &sp); dp = pg_any_to_server(sp, size - 1, PG_UTF8); result = cstring_to_text(dp); if (dp != sp) pfree(dp); if (BIO_free(membuf) != 1) elog(ERROR, "could not free OpenSSL BIO structure"); PG_RETURN_TEXT_P(result); }
/* * Convert a Python unicode object to a Python string/bytes object in * PostgreSQL server encoding. Reference ownership is passed to the * caller. */ PyObject * PLyUnicode_Bytes(PyObject *unicode) { PyObject *bytes, *rv; char *utf8string, *encoded; /* First encode the Python unicode object with UTF-8. */ bytes = PyUnicode_AsUTF8String(unicode); if (bytes == NULL) PLy_elog(ERROR, "could not convert Python Unicode object to bytes"); utf8string = PyBytes_AsString(bytes); if (utf8string == NULL) { Py_DECREF(bytes); PLy_elog(ERROR, "could not extract bytes from encoded string"); } /* * Then convert to server encoding if necessary. * * PyUnicode_AsEncodedString could be used to encode the object directly * in the server encoding, but Python doesn't support all the encodings * that PostgreSQL does (EUC_TW and MULE_INTERNAL). UTF-8 is used as an * intermediary in PLyUnicode_FromString as well. */ if (GetDatabaseEncoding() != PG_UTF8) { PG_TRY(); { encoded = pg_any_to_server(utf8string, strlen(utf8string), PG_UTF8); } PG_CATCH(); { Py_DECREF(bytes); PG_RE_THROW(); } PG_END_TRY(); } else encoded = utf8string; /* finally, build a bytes object in the server encoding */ rv = PyBytes_FromStringAndSize(encoded, strlen(encoded)); /* if pg_any_to_server allocated memory, free it now */ if (utf8string != encoded) pfree(encoded); Py_DECREF(bytes); return rv; }
/* * Return a strdup'ed string converted from the specified encoding to the * database encoding. */ static char * db_encoding_strdup(int encoding, const char *str) { char *pstr; char *mstr; /* convert the string to the database encoding */ pstr = pg_any_to_server(str, strlen(str), encoding); mstr = strdup(pstr); if (pstr != str) pfree(pstr); return mstr; }
/* * On WIN32, strftime() returns the encoding in CP_ACP (the default * operating system codpage for that computer), which is likely different * from SERVER_ENCODING. This is especially important in Japanese versions * of Windows which will use SJIS encoding, which we don't support as a * server encoding. * * So, instead of using strftime(), use wcsftime() to return the value in * wide characters (internally UTF16) and then convert it to the appropriate * database encoding. * * Note that this only affects the calls to strftime() in this file, which are * used to get the locale-aware strings. Other parts of the backend use * pg_strftime(), which isn't locale-aware and does not need to be replaced. */ static size_t strftime_win32(char *dst, size_t dstlen, const char *format, const struct tm * tm) { size_t len; wchar_t wformat[8]; /* formats used below need 3 bytes */ wchar_t wbuf[MAX_L10N_DATA]; /* get a wchar_t version of the format string */ len = MultiByteToWideChar(CP_UTF8, 0, format, -1, wformat, lengthof(wformat)); if (len == 0) elog(ERROR, "could not convert format string from UTF-8: error code %lu", GetLastError()); len = wcsftime(wbuf, MAX_L10N_DATA, wformat, tm); if (len == 0) { /* * strftime failed, possibly because the result would not fit in * MAX_L10N_DATA. Return 0 with the contents of dst unspecified. */ return 0; } len = WideCharToMultiByte(CP_UTF8, 0, wbuf, len, dst, dstlen - 1, NULL, NULL); if (len == 0) elog(ERROR, "could not convert string to UTF-8: error code %lu", GetLastError()); dst[len] = '\0'; if (GetDatabaseEncoding() != PG_UTF8) { char *convstr = pg_any_to_server(dst, len, PG_UTF8); if (convstr != dst) { strlcpy(dst, convstr, dstlen); len = strlen(dst); pfree(convstr); } } return len; }
/* * Convert an X509 subject name to a cstring. * */ static char * X509_NAME_to_cstring(X509_NAME *name) { BIO *membuf = BIO_new(BIO_s_mem()); int i, nid, count = X509_NAME_entry_count(name); X509_NAME_ENTRY *e; ASN1_STRING *v; const char *field_name; size_t size; char nullterm; char *sp; char *dp; char *result; (void) BIO_set_close(membuf, BIO_CLOSE); for (i = 0; i < count; i++) { e = X509_NAME_get_entry(name, i); nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(e)); v = X509_NAME_ENTRY_get_data(e); field_name = OBJ_nid2sn(nid); if (!field_name) field_name = OBJ_nid2ln(nid); BIO_printf(membuf, "/%s=", field_name); ASN1_STRING_print_ex(membuf, v, ((ASN1_STRFLGS_RFC2253 & ~ASN1_STRFLGS_ESC_MSB) | ASN1_STRFLGS_UTF8_CONVERT)); } /* ensure null termination of the BIO's content */ nullterm = '\0'; BIO_write(membuf, &nullterm, 1); size = BIO_get_mem_data(membuf, &sp); dp = pg_any_to_server(sp, size - 1, PG_UTF8); result = pstrdup(dp); if (dp != sp) pfree(dp); BIO_free(membuf); return result; }
Datum pgp_armor_headers(PG_FUNCTION_ARGS) { FuncCallContext *funcctx; pgp_armor_headers_state *state; char *utf8key; char *utf8val; HeapTuple tuple; TupleDesc tupdesc; AttInMetadata *attinmeta; if (SRF_IS_FIRSTCALL()) { text *data = PG_GETARG_TEXT_PP(0); int res; MemoryContext oldcontext; funcctx = SRF_FIRSTCALL_INIT(); /* we need the state allocated in the multi call context */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* Build a tuple descriptor for our result type */ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) elog(ERROR, "return type must be a row type"); attinmeta = TupleDescGetAttInMetadata(tupdesc); funcctx->attinmeta = attinmeta; state = (pgp_armor_headers_state *) palloc(sizeof(pgp_armor_headers_state)); res = pgp_extract_armor_headers((uint8 *) VARDATA_ANY(data), VARSIZE_ANY_EXHDR(data), &state->nheaders, &state->keys, &state->values); if (res < 0) ereport(ERROR, (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION), errmsg("%s", px_strerror(res)))); MemoryContextSwitchTo(oldcontext); funcctx->user_fctx = state; } funcctx = SRF_PERCALL_SETUP(); state = (pgp_armor_headers_state *) funcctx->user_fctx; if (funcctx->call_cntr >= state->nheaders) SRF_RETURN_DONE(funcctx); else { char *values[2]; /* we assume that the keys (and values) are in UTF-8. */ utf8key = state->keys[funcctx->call_cntr]; utf8val = state->values[funcctx->call_cntr]; values[0] = pg_any_to_server(utf8key, strlen(utf8key), PG_UTF8); values[1] = pg_any_to_server(utf8val, strlen(utf8val), PG_UTF8); /* build a tuple */ tuple = BuildTupleFromCStrings(funcctx->attinmeta, values); SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); } }