From 9eb11d19b13870292f3ccd340c67d7e148761db5 Mon Sep 17 00:00:00 2001
From: Vadim Zeitlin <vadim@wxwidgets.org>
Date: Sun, 29 Oct 2006 21:49:37 +0000
Subject: [PATCH] escape special SQL chars in where clauses (patch 1204728)

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42676 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
---
 docs/latex/wx/db.tex   | 19 +++++++++++++++++++
 include/wx/db.h        |  3 +++
 src/common/db.cpp      | 22 ++++++++++++++++++++++
 src/common/dbtable.cpp |  2 +-
 4 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/docs/latex/wx/db.tex b/docs/latex/wx/db.tex
index 88cd6ca6e3..e7264d3c24 100644
--- a/docs/latex/wx/db.tex
+++ b/docs/latex/wx/db.tex
@@ -707,6 +707,25 @@ Drops the data table view named in 'viewName'.
 
 If the view does not exist, this function will return true.  Note that views are not supported with all datasources.
 
+\membersection{wxDb::EscapeSqlChars}\label{wxdbescapesqlchars}
+
+\func{wxString}{EscapeSqlChars}{\param{const wxString\& }{value}}
+
+This function is used internally by wxWidgets while building SQL statements.
+It has been provided to help users who wish to explicity construct SQL
+statements to be sent to the server.  The function takes the value passed and
+returns it with any special characters escaped.  Which characters are
+considered special depends on what type of datasource the object is connected
+to.  For example, most database servers use a backslash as the escape
+character; if the value passed contains a backlash it will be replaced with a
+double backslash before it is passed to the server.  This function can be used
+to avoid passing statements with syntax errors to the server as well as prevent
+SQL injection attacks.
+
+\wxheading{Parameters}
+
+\docparam{value}{The value to be escaped.}
+
 \membersection{wxDb::ExecSql}\label{wxdbexecsql}
 
 \func{bool}{ExecSql}{\param{const wxString \&}{pSqlStmt}}
diff --git a/include/wx/db.h b/include/wx/db.h
index 68c723b5eb..bdd7ffb010 100644
--- a/include/wx/db.h
+++ b/include/wx/db.h
@@ -734,6 +734,9 @@ public:
 
     bool         FwdOnlyCursors(void)  {return fwdOnlyCursors;}
 
+    // return the string with all special SQL characters escaped
+    wxString     EscapeSqlChars(const wxString& value);
+
     // These two functions are provided strictly for use by wxDbTable.
     // DO NOT USE THESE FUNCTIONS, OR MEMORY LEAKS MAY OCCUR
     void         incrementTableCount() { nTables++; return; }
diff --git a/src/common/db.cpp b/src/common/db.cpp
index a43f461158..0e99d44d21 100644
--- a/src/common/db.cpp
+++ b/src/common/db.cpp
@@ -4086,6 +4086,28 @@ bool wxDb::ModifyColumn(const wxString &tableName, const wxString &columnName,
 
 } // wxDb::ModifyColumn()
 
+/********** wxDb::EscapeSqlChars() **********/
+wxString wxDb::EscapeSqlChars(const wxString& valueOrig)
+{
+    wxString value(valueOrig);
+    switch (Dbms())
+    {
+        case dbmsACCESS:
+            // Access doesn't seem to care about backslashes, so only escape single quotes.
+            value.Replace(wxT("'"), wxT("''"));
+            break;
+
+        default:
+            // All the others are supposed to be the same for now, add special
+            // handling for them if necessary
+            value.Replace(wxT("\\"), wxT("\\\\"));
+            value.Replace(wxT("'"), wxT("\\'"));
+            break;
+    }
+
+    return value;
+} // wxDb::EscapeSqlChars()
+
 
 /********** wxDbGetConnection() **********/
 wxDb WXDLLIMPEXP_ODBC *wxDbGetConnection(wxDbConnectInf *pDbConfig, bool FwdOnlyCursors)
diff --git a/src/common/dbtable.cpp b/src/common/dbtable.cpp
index 1a97227993..dd88239248 100644
--- a/src/common/dbtable.cpp
+++ b/src/common/dbtable.cpp
@@ -1308,7 +1308,7 @@ void wxDbTable::BuildWhereClause(wxString &pWhereClause, int typeOfWhere,
                 case SQL_C_WCHAR:
 #endif
                 //case SQL_C_WXCHAR:  SQL_C_WXCHAR is covered by either SQL_C_CHAR or SQL_C_WCHAR
-                    colValue.Printf(wxT("'%s'"), (UCHAR FAR *) colDefs[colNumber].PtrDataObj);
+                    colValue.Printf(wxT("'%s'"), GetDb()->EscapeSqlChars((UCHAR FAR *)colDefs[colNumber].PtrDataObj).c_str());
                     break;
                 case SQL_C_SHORT:
                 case SQL_C_SSHORT:
-- 
2.50.0

