replace double backslash with single backslash in haskell - postgresql

I want to replace "\\" from a bytestring sequence (Data.ByteString)
with "\", but due to the internal escaping of "\" it won't work.
Consider following example:
The original bytestring:
"\159\DEL*\150\222/\129vr\205\241=mA\192\184"
After storing in and re-reading from a database I obtain following
bytestring:
"\"\\159\\DEL*\\150\\222/\\129vr\\205\\241=mA\\192\\184\""
Imagine that the bytestring is used as a cryptographic key, which
is now a wrong key due to the invalid characters in the sequence.
This problem actually arises from the wrong database representation
(varchar instead of bytea) because it's otherwise considered as an invalid utf-8 sequence.
I have tried to replace the invalid characters using some sort of
split-modify-concat approach, but all I get is something without
any backslash inside the sequence, because I can't insert a single backslash
into a bytestring.
I really ask for your help.

Perhaps using read will work for you:
import Data.ByteString.Char8 as BS
bad = BS.pack "\"\\159\\DEL*\\150\\222/\\129vr\\205\\241=mA\\192\\184\""
good = read (BS.unpack bad) :: BS.ByteString
-- returns: "\159\DEL*\150\222/\129vr\205\241=mA\192\184"
You can also use readMaybe instead for safer parsing.

possibly you want the postgresql expression
substring(ByteString from e'^\\"(.*)\\"$')::bytea
that will give a bytea result that can be used in queries or in an alter table-using DDL

Related

Postgres - PreparedStatement.setString sending incorrect data

I'm trying to use select pg_catalog.hashtext(?) via JDBC PreparedStatement, and running into a weird behavior.
For most strings it works fine, e.g. the following randomly generated string:
"Fm_:VW:<jBGOl$K "
and I get the correct hash back: 641495800
But for some of the strings, it spits back a hash that doesn't match the value when I query directly the DB via psql or some other tool such as DataGrip.
For instance, this works fine:
"}F:d(2 dS8xt9KP0$~tYw;R(V"!2[7&Xs2Wj#5 k|F[}%.ZQ^93~
Cuk&93d!t8b|{4F&{1j{.;C},1s/b&wYZ Ckc5vqy|e+5&5EW%RQ6F0>R4#h.6$iU>{=kl!{e(CTH^DvN/<eG9 bjHx#9=&& G$W_Y =! j\q3T;[H.ve-~>S5j8eI.gWQmg. C!WpWK0z>f?^^LLMO:3R';!4eVxU2)~1F6Zs!p0 F'1b*G:xBO5cN{O'1P~
fj5g%IcT}]w ;;DlD Q~D=wT qN7zON]/J9Heh3qwJ #n qMTG\M7#h,8JUP3Sl}L:wb7#bRc&eIWp\z>HuwZI2Ej5;v7M _8DU.d?mvD| !rS!XS;8QQYh6D=BMJ5m2$>cR ob#'{dCOr#NzDk c!JtQbzCg&#dG:qtHy)O4 ohWQ`ed
2 O'HmHt\<SO
gHKAo`WIb"HF\LrpKKDsW -e##v%RS+,-61lze bd|tyl);A0h":O40O71b(0cDM57gTFL~[7ksp
_Nx:"
But this doesn't:
".4X$!S"s
3E&fJZP*yC#6 ii7^D%Nj3Qn(]:&ykP3(%9 Ww}| ZOmcZ:(w<d= On/m\)vfAEu)s:Yy<17:l9GImT!BgH,FG(:DanwL|3'#XS
a_+nwbqPYBu[DWW`VbBKzF%CnaYpH "
Now, I tried using Statement instead of PreparedStatement along with a String concatenated query, and that works fine, as long as I escape single-quote characters (') with two-single quotes ('') before executing the query. So it appears that somehow PreparedStatement.setString is doing something weird with the String that I pass to it.
Note: The reason I'm testing this with random strings is because my code needs to be able to work with any UTF-8 string that's thrown at it. This test only uses ASCII, and it's already failing in some cases. I don't want to use Statement as that opens up a whole different discussion.

By entering values into table, command line does not work [duplicate]

I have a table test(id,name).
I need to insert values like: user's log, 'my user', customer's.
insert into test values (1,'user's log');
insert into test values (2,''my users'');
insert into test values (3,'customer's');
I am getting an error if I run any of the above statements.
If there is any method to do this correctly please share. I don't want any prepared statements.
Is it possible using sql escaping mechanism?
String literals
Escaping single quotes ' by doubling them up → '' is the standard way and works of course:
'user's log' -- incorrect syntax (unbalanced quote)
'user''s log'
Plain single quotes (ASCII / UTF-8 code 39), mind you, not backticks `, which have no special purpose in Postgres (unlike certain other RDBMS) and not double-quotes ", used for identifiers.
In old versions or if you still run with standard_conforming_strings = off or, generally, if you prepend your string with E to declare Posix escape string syntax, you can also escape with the backslash \:
E'user\'s log'
Backslash itself is escaped with another backslash. But that's generally not preferable.
If you have to deal with many single quotes or multiple layers of escaping, you can avoid quoting hell in PostgreSQL with dollar-quoted strings:
'escape '' with '''''
$$escape ' with ''$$
To further avoid confusion among dollar-quotes, add a unique token to each pair:
$token$escape ' with ''$token$
Which can be nested any number of levels:
$token2$Inner string: $token1$escape ' with ''$token1$ is nested$token2$
Pay attention if the $ character should have special meaning in your client software. You may have to escape it in addition. This is not the case with standard PostgreSQL clients like psql or pgAdmin.
That is all very useful for writing PL/pgSQL functions or ad-hoc SQL commands. It cannot alleviate the need to use prepared statements or some other method to safeguard against SQL injection in your application when user input is possible, though. #Craig's answer has more on that. More details:
SQL injection in Postgres functions vs prepared queries
Values inside Postgres
When dealing with values inside the database, there are a couple of useful functions to quote strings properly:
quote_literal() or quote_nullable() - the latter outputs the unquoted string NULL for null input.
There is also quote_ident() to double-quote strings where needed to get valid SQL identifiers.
format() with the format specifier %L is equivalent to quote_nullable().
Like: format('%L', string_var)
concat() or concat_ws() are typically no good for this purpose as those do not escape nested single quotes and backslashes.
According to PostgreSQL documentation (4.1.2.1. String Constants):
To include a single-quote character within a string constant, write
two adjacent single quotes, e.g. 'Dianne''s horse'.
See also the standard_conforming_strings parameter, which controls whether escaping with backslashes works.
This is so many worlds of bad, because your question implies that you probably have gaping SQL injection holes in your application.
You should be using parameterized statements. For Java, use PreparedStatement with placeholders. You say you don't want to use parameterised statements, but you don't explain why, and frankly it has to be a very good reason not to use them because they're the simplest, safest way to fix the problem you are trying to solve.
See Preventing SQL Injection in Java. Don't be Bobby's next victim.
There is no public function in PgJDBC for string quoting and escaping. That's partly because it might make it seem like a good idea.
There are built-in quoting functions quote_literal and quote_ident in PostgreSQL, but they are for PL/PgSQL functions that use EXECUTE. These days quote_literal is mostly obsoleted by EXECUTE ... USING, which is the parameterised version, because it's safer and easier. You cannot use them for the purpose you explain here, because they're server-side functions.
Imagine what happens if you get the value ');DROP SCHEMA public;-- from a malicious user. You'd produce:
insert into test values (1,'');DROP SCHEMA public;--');
which breaks down to two statements and a comment that gets ignored:
insert into test values (1,'');
DROP SCHEMA public;
--');
Whoops, there goes your database.
In postgresql if you want to insert values with ' in it then for this you have to give extra '
insert into test values (1,'user''s log');
insert into test values (2,'''my users''');
insert into test values (3,'customer''s');
you can use the postrgesql chr(int) function:
insert into test values (2,'|| chr(39)||'my users'||chr(39)||');
When I used Python to insert values into PostgreSQL, I also met the question: column "xxx" does not exist.
The I find the reason in wiki.postgresql:
PostgreSQL uses only single quotes for this (i.e. WHERE name = 'John'). Double quotes are used to quote system identifiers; field names, table names, etc. (i.e. WHERE "last name" = 'Smith').
MySQL uses ` (accent mark or backtick) to quote system identifiers, which is decidedly non-standard.
It means PostgreSQL can use only single quote for field names, table names, etc. So you can not use single quote in value.
My situation is: I want to insert values "the difference of it’s adj for sb and it's adj of sb" into PostgreSQL.
How I figure out this problem:
I replace ' with ’, and I replace " with '. Because PostgreSQL value does not support double quote.
So I think you can use following codes to insert values:
insert into test values (1,'user’s log');
insert into test values (2,'my users');
insert into test values (3,'customer’s');
If you need to get the work done inside Pg:
to_json(value)
https://www.postgresql.org/docs/9.3/static/functions-json.html#FUNCTIONS-JSON-TABLE
You must have to add an extra single quotes -> ' and make doubling quote them up like below examples -> ' ' is the standard way and works of course:
Wrong way: 'user's log'
Right way: 'user''s log'
problem:
insert into test values (1,'user's log');
insert into test values (2,''my users'');
insert into test values (3,'customer's');
Solutions:
insert into test values (1,'user''s log');
insert into test values (2,'''my users''');
insert into test values (3,'customer''s');

hstore value with single quote

I asked similar question here for: hstore value with space. And get solved by user: Clodoaldo Neto. Now I have come across next case with string containing single quote.
SELECT 'k=>"name", v=>"St. Xavier's Academy"'::hstore;
I tried it by using dollar-quoted string constant by reading http://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-CONSTANTS
SELECT 'k=>"name", v=>$$St. Xavier's Academy$$'::hstore;
But I couldn't get it right.
How to make postgresql hstore using strings containing single quote?
It seems like there are more such exceptions possible for this query. How to address them all at once?
You can escape the embedded single quote that same way you'd escape any other single quote inside a string literal: double it.
SELECT 'k=>"name", v=>"St. Xavier''s Academy"'::hstore;
-- ------------------------------^^
Alternatively, you could dollar quote the whole string:
SELECT $$k=>"name", v=>"St. Xavier's Academy"$$::hstore;
Whatever interface you're using to talk to PostgreSQL should be taking care of these quoting and escaping issues. If you're using manual string wrangling to build your SQL then you should be using your driver's quoting and placeholder methods.
hstore's internal parsing understands double quotes around keys:
Double-quote keys and values that include whitespace, commas, =s or >s.
Dollar quoting is, as you noted, for SQL string literals, hstore's parser doesn't know what they mean.

How to update a record with literal percent literal (%) in PostgreSQL without saving it as "\%"

I need to update a record, which contains literal percent signs, using PostgreSQL in Railo. The query looks like
<cfquery>
update foo set bar = 'string with % in it %'
</cfQuery>
It throws error as ColdFusion normally interprets it as a wildcard character. I can escape it using the following query.
<cfquery>
update foo set bar = 'string with escaped \% in it \%'
</cfQuery>
However, the record now contains "\%" in the database and will be displayed on the page as "\%".
I found a documentation with an example of escaping percent sign in a SELECT. But it does not work for me: syntax error at or near "ESCAPE".
SELECT emp_discount
FROM Benefits
WHERE emp_discount LIKE '10\%'
ESCAPE '\';
Is there a better to achieve the same goal? The underlining database is PostgreSQL. Thanks!
Queryparameters escape special characters. Yet another reason to use them.

Perl JSON pound sign escaping

I am trying to use a web API of a service written in Perl (OTRS).
The data is sent in JSON format.
One of the string values inside the JSON structure contains a pound sign, which in apparently is used as a comment character in JSON.
This results in a parsing error:
unexpected end of string while parsing
JSON string
I couldn't find how to escape the character in order to get the string parsed successfully.
The obvious slash escaping results in:
illegal backslash escape sequence in
string
Any ideas how to escape it?
Update:
The URL I am trying to use looks something like that (simplified but still causes the error):
http://otrs.server.url/otrs/json.pl?User=username&Password=password&Object=TicketObject&Method=ArticleSend&Data={"Subject":"[Ticket#100000] Test Ticket from OTRS"}
Use Uri::escape:
use URI::Escape;
my $safe = uri_escape($url);
See rfc1738 for the list of characters which can be unsafe.
The hash symbol, #, has a special meaning in URLs, not in JSON. Your URL is probably getting truncated at the hash before the remove server even sees it:
http://otrs.server.url/otrs/json.pl?User=username&Password=password&Object=TicketObject&Method=ArticleSend&Data={"Subject":"[Ticket
And that means that the remote server gets mangled JSON in Data. The solution is to URL encode your parameters before pasting them together to form your URL; eugene y tells you how to do this.