{"action":"created","issue":{"url":"https://api.github.com/repos/developerforce/Force.com-Toolkit-for-PHP/issues/51","repository_url":"https://api.github.com/repos/developerforce/Force.com-Toolkit-for-PHP","labels_url":"https://api.github.com/repos/developerforce/Force.com-Toolkit-for-PHP/issues/51/labels{/name}","comments_url":"https://api.github.com/repos/developerforce/Force.com-Toolkit-for-PHP/issues/51/comments","events_url":"https://api.github.com/repos/developerforce/Force.com-Toolkit-for-PHP/issues/51/events","html_url":"https://github.com/developerforce/Force.com-Toolkit-for-PHP/issues/51","id":134887523,"number":51,"title":"Provide clarification / standard method for escaping string for use in SOQL","user":{"login":"leewillis77","id":1097338,"avatar_url":"https://avatars.githubusercontent.com/u/1097338?v=3","gravatar_id":"","url":"https://api.github.com/users/leewillis77","html_url":"https://github.com/leewillis77","followers_url":"https://api.github.com/users/leewillis77/followers","following_url":"https://api.github.com/users/leewillis77/following{/other_user}","gists_url":"https://api.github.com/users/leewillis77/gists{/gist_id}","starred_url":"https://api.github.com/users/leewillis77/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/leewillis77/subscriptions","organizations_url":"https://api.github.com/users/leewillis77/orgs","repos_url":"https://api.github.com/users/leewillis77/repos","events_url":"https://api.github.com/users/leewillis77/events{/privacy}","received_events_url":"https://api.github.com/users/leewillis77/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2016-02-19T15:07:51Z","updated_at":"2016-02-27T18:17:05Z","closed_at":null,"body":"Hi; \r\n\r\nHopefully I'm missing something here, however I've read through countless articles and not been able to find an answer to what I think is a rather basic question. \r\n\r\nConsider the following code:\r\n\r\n```php\r\n<?php\r\n$client = new SforceEnterpriseClient();\r\n$client->createConnection($this->wsdl);\r\n$client->login($this->username, $this->password . $this->security_token);\r\n$query = \"SELECT Id\r\n            FROM Contact\r\n           WHERE Email = '$email'\r\n        ORDER BY LastModifiedDate ASC\";\r\n$response = $client->query($query);\r\n```\r\n\r\nAssuming that ```$email``` is a user-supplied variable then it's clear that it should be escaped to prevent query-injection vulnerabilities. However - it's not clear from any of the documentation *how* that should be escaped. \r\n\r\nThis page looks the most promising:\r\nhttps://developer.salesforce.com/page/Secure_Coding_SQL_Injection#SOQL_INJECTION_And_Force.com_APIs\r\n\r\nHowever it basically says to use parameterizied prepared queries (Which aren't supported via the SOAP API), or PDO to escape the string (Which requires a database connection, and will escape only for the context of that particular database connection). \r\n\r\nIt doesn't help that none of the examples listed at https://developer.salesforce.com/page/Getting_Started_with_the_Force.com_Toolkit_for_PHP or https://developer.salesforce.com/page/Tksample.php include any dynamic variables, or any escaping. \r\n\r\nPlease can you clarify the escaping method that is required to escape data in SOQL strings?\r\n\r\nIdeally this library should either:\r\n\r\na) Expose (and recommend the use of) a parameterized query method that handles escaping internally, e.g. \r\n```php\r\n<?php\r\n$query = \"SELECT Id\r\n                FROM Contact\r\n               WHERE Email = :email\r\n            ORDER BY LastModifiedDate ASC\";\r\n$response = $client->query($query, array(':email' => $email));\r\n```\r\n\r\nb) Provide a string escaping function so developers aren't encouraged to roll their own , e.g.\r\n```php\r\n<?php\r\n$email = $client->escapeString($email);\r\n$query = \"SELECT Id\r\n            FROM Contact\r\n           WHERE Email = $email\r\n        ORDER BY LastModifiedDate ASC\";\r\n$response = $client->query($query);\r\n```\r\n\r\nApologies if this is already covered somewhere - but as someone new to the SalesForce APIs it's not easy to find :)"},"comment":{"url":"https://api.github.com/repos/developerforce/Force.com-Toolkit-for-PHP/issues/comments/189698032","html_url":"https://github.com/developerforce/Force.com-Toolkit-for-PHP/issues/51#issuecomment-189698032","issue_url":"https://api.github.com/repos/developerforce/Force.com-Toolkit-for-PHP/issues/51","id":189698032,"user":{"login":"hatzopoulos","id":1771931,"avatar_url":"https://avatars.githubusercontent.com/u/1771931?v=3","gravatar_id":"","url":"https://api.github.com/users/hatzopoulos","html_url":"https://github.com/hatzopoulos","followers_url":"https://api.github.com/users/hatzopoulos/followers","following_url":"https://api.github.com/users/hatzopoulos/following{/other_user}","gists_url":"https://api.github.com/users/hatzopoulos/gists{/gist_id}","starred_url":"https://api.github.com/users/hatzopoulos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hatzopoulos/subscriptions","organizations_url":"https://api.github.com/users/hatzopoulos/orgs","repos_url":"https://api.github.com/users/hatzopoulos/repos","events_url":"https://api.github.com/users/hatzopoulos/events{/privacy}","received_events_url":"https://api.github.com/users/hatzopoulos/received_events","type":"User","site_admin":false},"created_at":"2016-02-27T18:17:05Z","updated_at":"2016-02-27T18:17:05Z","body":"At least for the [`FIND {SearchQuery}`](https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_sosl_find.htm) functionality, the docs say reserved characters are `? & | ! { } [ ] ( ) ^ ~ * : \\ \" ' + -` and to properly escape them. Please correct me if I'm mistaken but I assumed SOQL followed the same rules similar to Oracle (or MySQL) for escaping. \r\n\r\n```php\r\n\r\n// $example_partial_sql .= \"FIND {\".soql_string_literal($email).\"} IN EMAIL FIELDS\";\r\n\r\nfunction soql_string_literal($str) {\r\n\t\r\n\t// ? & | ! { } [ ] ( ) ^ ~ * : \\ \" ' + -\r\n\t$characters  = array(\r\n\t\t'\\\\',\r\n\t\t'?' ,\r\n\t\t'&' ,\r\n\t\t'|' ,\r\n\t\t'!' ,\r\n\t\t'{' ,\r\n\t\t'}' ,\r\n\t\t'[' ,\r\n\t\t']' ,\r\n\t\t'(' ,\r\n\t\t')' ,\r\n\t\t'^' ,\r\n\t\t'~' ,\r\n\t\t'*' ,\r\n\t\t':' ,\r\n\t\t'\"' ,\r\n\t\t'\\'',\r\n\t\t'+' ,\r\n\t\t'-');\r\n\t$replacement = array(\r\n\t\t'\\\\\\\\',\r\n\t\t'\\?',\r\n\t\t'\\&',\r\n\t\t'\\|',\r\n\t\t'\\!',\r\n\t\t'\\{',\r\n\t\t'\\}',\r\n\t\t'\\[',\r\n\t\t'\\]',\r\n\t\t'\\(',\r\n\t\t'\\)',\r\n\t\t'\\^',\r\n\t\t'\\~',\r\n\t\t'\\*',\r\n\t\t'\\:',\r\n\t\t'\\\"',\r\n\t\t'\\\\\\'',\r\n\t\t'\\+',\r\n\t\t'\\-'\r\n\t);\r\n\treturn str_replace($characters, $replacement, $str);\r\n\t\r\n}\r\n```"}}