Salesforce.com interface to directly access Salesforce.com
Dependencies: HTTPClient-SSL MbedJSONValue
Dependents: df-2014-salesforce-hrm-k64f
Fork of SalesforceInterface by
Diff: SalesforceInterface.cpp
- Revision:
- 8:47db53cd5884
- Parent:
- 7:97ea5ef906f7
- Child:
- 9:a254fcd904be
--- a/SalesforceInterface.cpp Sun Sep 21 07:08:51 2014 +0000 +++ b/SalesforceInterface.cpp Mon Sep 22 04:28:02 2014 +0000 @@ -21,6 +21,16 @@ #define SF_OAUTH_REQUEST_BODY "grant_type=password&client_id=%s&client_secret=%s&username=%s&password=%s" #define SF_HTTP_AUTH_HEADER "Authorization: Bearer %s" + // search tokens for URLS in salesforce ID + #define SF_URLS_START_TOKEN "\"urls\":" + #define SF_URLS_STOP_TOKEN "}," + + // salesforce QUERY specifier within URL + #define SF_QUERY_URL_SPECIFIER "q=" + + // salesforce URL API version token + #define SF_URL_API_VER_TOKEN "{version}" + // include class definition #include "SalesforceInterface.h" @@ -40,6 +50,9 @@ this->m_http_status = HTTP_OK; this->m_http_response_code = -1; RESET_BUFFER(this->m_http_redirection_url); + RESET_BUFFER(this->m_salesforce_id); + memset(this->m_salesforce_api,0,SALESFORCE_API_VERSION_LENGTH); + strcpy(this->m_salesforce_api,SALESFORCE_API_VERSION); this->resetOauthToken(); } @@ -77,6 +90,9 @@ bool SalesforceInterface::haveCreds() { return this->m_have_creds; } HTTPResult SalesforceInterface::httpStatus() { return this->m_http_status; } int SalesforceInterface::httpResponseCode() { return this->m_http_response_code; } + void SalesforceInterface::setSalesforceAPIVersion(int version) { sprintf(this->m_salesforce_api,"%d",version); } + void SalesforceInterface::setSalesforceAPIVersion(char *version) { if (version != NULL && strlen(version) > 0 && strlen(version) < SALESFORCE_API_VERSION_LENGTH) strcpy(this->m_salesforce_api,version); } + char *SalesforceInterface::getSalesforceAPIVersion() { return this->m_salesforce_api; } // reset our oauth token void SalesforceInterface::resetOauthToken() { @@ -120,7 +136,13 @@ // TODO: we currently only return fill status. Later we may want to check dates too... return this->m_oauth_token.valid; -} + } + + // do we have a valid salesforce.com ID? + bool SalesforceInterface::haveSalesforceID() { + if (this->m_salesforce_id != NULL && strlen(this->m_salesforce_id) > 0) return true; + return false; + } // check and get our OAUTH token void SalesforceInterface::checkAndGetOauthToken() { @@ -181,11 +203,12 @@ } // Salesforce.com: Get our ID - char *SalesforceInterface::getSalesforceID(char *output_buffer,int output_buffer_length) { + char *SalesforceInterface::getSalesforceID() { // proceed only if we have a valid OAUTH Token if (this->validOauthToken() == true) { // pull the ID from salesforce - char *id = this->invoke(this->oauth()->id.c_str(),output_buffer,output_buffer_length); + RESET_BUFFER(this->m_salesforce_id); + char *id = this->invoke(this->oauth()->id.c_str(),this->m_salesforce_id,MAX_BUFFER_LENGTH); // log any error status and return what we have... if (this->httpStatus() != HTTP_OK) this->logger()->log("Unable to get Salesforce ID: status=%d httpCode=%d",this->httpStatus(),this->httpResponseCode()); @@ -198,6 +221,44 @@ return NULL; } + // QUERY: Salesforce.com + char *SalesforceInterface::query(char *query_str,char *output_buffer,int output_buffer_length) { + // first we have to ensure that we have valid salesforce ID + if (this->haveSalesforceID()) { + // get the QUERY URL + ALLOC_BUFFER(url); + char *sf_url = this->getSalesforceURL("query",url,MAX_BUFFER_LENGTH); + if (sf_url != NULL && strlen(sf_url) > 0) { + // make sure that the query string is ready to ship... + ALLOC_SML_BUFFER(tmp_query); + + // replace all spaces in query with "+" + strcpy(tmp_query,query_str); + this->replace(tmp_query,' ','+'); // will modify tmp_query directly... + + // customize the URL with our (formatted) query string + string str_url(sf_url); + str_url[str_url.length()-1] = '?'; // remove the slash and add a ? + str_url = str_url + SF_QUERY_URL_SPECIFIER + tmp_query; // add the query specifier + + // DEBUG - show the query URL + DEBUG("query URL: %s",str_url.c_str()); + + // invoke with GET + return this->invoke((const char *)str_url.c_str(),output_buffer,output_buffer_length); + } + else { + // unable to find the query URL... + this->logger()->log("query: error - unable to find query URL in salesforce ID..."); + } + } + else { + // dont have a valid salesforce ID + this->logger()->log("query: error - no valid salesforced ID was found..."); + } + return NULL; + } + // Salesforce.com Invoke: defaults to GET char *SalesforceInterface::invoke(const char *url,char *output_buffer,int output_buffer_len) { return this->invoke(url,NUM_TYPES,NULL,0,output_buffer,output_buffer_len,GET); @@ -328,4 +389,78 @@ else this->logger()->log("invocation failed with HTTP error code=%d status=%d",this->httpResponseCode(),this->httpStatus()); return NULL; } - \ No newline at end of file + + // find the specific URL in our salesforce ID + char *SalesforceInterface::getSalesforceURL(char *key,char *url_buffer,int url_buffer_length) { + // due to MbedJSONValue limitations - we have to manually pull out the specific JSON from our salesforce ID + int start = (int)strstr(this->m_salesforce_id,SF_URLS_START_TOKEN); + if (start >= 0) { + start += strlen(SF_URLS_START_TOKEN); + int stop = (int)strstr((char *)start,SF_URLS_STOP_TOKEN); + if (stop >= 0 && stop > start) { + // calculate the length + int length = stop - start + 1; + + // copy over the "urls" json from the salesforce ID + ALLOC_BUFFER(urls); + int start_index = (start - (int)this->m_salesforce_id); + for(int i=0;i<length;++i) urls[i] = this->m_salesforce_id[start_index+i]; + + // use MbedJSONValue to parse the "urls" json + MbedJSONValue parsed_urls; + parse(parsed_urls,urls); + + // find the appropriate URL and copy it + string target_url = parsed_urls[key].get<std::string>(); + + // replace the version of the string with our selected salesforce API version + string sf_version(this->getSalesforceAPIVersion()); + string version_tag(SF_URL_API_VER_TOKEN); + this->replace(target_url,version_tag,sf_version); + + // copy the final URL to our putput + memset(url_buffer,0,url_buffer_length); + strcpy(url_buffer,target_url.c_str()); + + // return the URL + return url_buffer; + } + } + return NULL; + } + + // simple char array replacement (modifies input string!) + void SalesforceInterface::replace(char *str,char orig_char,char new_char) { + int length = strlen(str); + for(int i=0;i<length;++i) if (str[i] == orig_char) str[i] = new_char; + } + + // + // substring replacement + // Credit: http://stackoverflow.com/questions/4643512/replace-substring-with-another-substring-c + // + void SalesforceInterface::replace(string& line, string& oldString, string& newString) { + const size_t oldSize = oldString.length(); + + // do nothing if line is shorter than the string to find + if( oldSize > line.length() ) return; + + const size_t newSize = newString.length(); + for( size_t pos = 0; ; pos += newSize ) { + + // Locate the substring to replace + pos = line.find( oldString, pos ); + if( pos == string::npos ) return; + if( oldSize == newSize ) { + + // if they're same size, use std::string::replace + line.replace( pos, oldSize, newString ); + } + else { + + // if not same size, replace by erasing and inserting + line.erase( pos, oldSize ); + line.insert( pos, newString ); + } + } +} \ No newline at end of file