Hello,

I've noticed that the API attempts to check the string length of various fields on the Drupal side before export, and then trims them if the mapped Salesforce field enforces a limit that's smaller than the current character count (around line 1060 of salesforce_api.module):

$max_len = $sf_field_definition['salesforce']['length'];
if ($max_len && drupal_strlen($object->$sf_fieldname) > $max_len) {
  $object->$sf_fieldname = substr($object->$sf_fieldname, 0, $max_len);
}

This seems to breakdown when the fields contains non-alphanumeric characters (e.g. Chinese). In this case, the entry will be trimmed to exactly n characters (n being defined by the Salesforce field characteristics) assuming alphanumeric characters, which may lead to a corrupt utf-8 string, and a string that is not actually n characters long.

I'm guessing that some mb_ereg() or utf8_encode() logic might be needed? I'm not so great with character encoding logic, so I don't have a solution off-hand, but I wanted to be sure to point this out and see if it is in fact a problem elsewhere.

Comments

rjacobs’s picture

Actually, I'm wondering if mb_substr() could just be dropped-in instead of substr() in the last line from the snippet above? Perhaps this has performance issues?

longwave’s picture

drupal_substr() is a multibyte safe version of substr()

http://api.drupal.org/api/drupal/includes--unicode.inc/function/drupal_s...

rjacobs’s picture

Even better!

EvanDonovan’s picture

So if I'm understanding #2 correctly, this is a one-liner fix?

rjacobs’s picture

Yeah, it's just the addition of "drupal_" to the "substr" part of line ~1060, making:

$max_len = $sf_field_definition['salesforce']['length'];
if ($max_len && drupal_strlen($object->$sf_fieldname) > $max_len) {
  $object->$sf_fieldname = drupal_substr($object->$sf_fieldname, 0, $max_len);
}

I wasn't sure if this needed a patch.... dealing with a patch just seems like more trouble than it's worth to change/test this. I just ran a test with some Chinese characters in a mapped field (that had a character limit) and it seems to work correctly with this change (the field got trimmed properly, etc.).

Not sure if it needs another tester, but I don't see much harm in the change either way, especially as drupal_substr() is advertised as using the same syntax/concept as substr():

http://api.drupal.org/api/drupal/includes--unicode.inc/function/drupal_s...

Makes me wonder if there are other places where substr() should be swapped-out with drupal_substr()... but that's another thing altogether.

longwave’s picture

substr() is only safe to use on known ASCII strings or where you explicitly want to deal with individual bytes. drupal_substr() should be used anywhere you are extracting characters from strings that might be UTF-8.

rjacobs’s picture

Yes, and it looks like drupal_substr() uses mb_substr() when it knows it's dealing with unicode characters and will otherwise do a bunch of calculations to find a safe trimming point. So it looks like the Drupal version of this function is built to get around these kinds of issues (such as the one in this thread) with one go-to trimming function.

rjacobs’s picture

Title: UTF-8 Support for string length calculation » Proper multibyte support for string operations

Also, I just noticed that running a module through coder under the 'minor' setting (detect even the most minor errors) will report all cases where it's recommended to "replace the string function with the drupal_ equivalent string functions". So it's looking like salesforce_api just needs to be put through coder.

kostajh’s picture

Status: Active » Closed (won't fix)
rjacobs’s picture

Status: Closed (won't fix) » Active

I just want to check and see why this was closed. From what I can see in the repository there are still cases in the 6.x-2.x and 7.x-2.x branches where substr() is used when drupal_substr() may be a better choice. I can't be 100% sure if it's just a matter of swapping these functions in these handful of places, but the conversation above indicates some attention may still be necessary to properly support utf-8.

I'm assuming this is no longer a problem in at least 7.x-3.x, as it sounds like that's a total re-factor.

If I'm missing something and this is in fact fixed in pre 7.x-3.x, I apologize.

kostajh’s picture

I went through the issue queue today and closed out old 6.x-2.x and 7.x-2.x issues that either (1) had no patches attached or (2) had patches attached but no review and didn't have comments from other users indicating they had been tested. I may have been a bit overzealous in which case, please feel free to open an issue.

That said, the 6.x-2.x branch is going to receive bug fixes marked RBTC, but the 7.x-3.x branch is the only one being actively developed at the moment. And since substr is not used in that branch, closing this issue seemed fine.

rjacobs’s picture

I'll make a patch for this momentarily... soon after opening this thread it looked like Evan was going to address this. I now see however that Evan is not so much involved on the development of this project anymore. Anyway, this can be quite a simple fix that may save people trouble.

rjacobs’s picture

Status: Active » Needs review
StatusFileSize
new1.01 KB
new1.01 KB

Ok, patches for 6.x-2.x and 7.x-2.x are attached. I had a quick scan of all module files and though there are several places where substr() could probably be swapped with drupal_substr() there is only one case where I see that it's particularly problematic to not use drupal_substr(). This is the case that this patch addresses. Please see also comment #5 for these specifics.

Even if this does not get a community review I'd encourage one of the maintainers to have a look at this. It's a pretty innocuous change and is as much about making sure the module follows Drupal coding standards as it is about fixing the problems highlighted in this thread.

Also note that the patches are git-formatted patches with include my authorship info. If this gets committed, I'd certainly love it if those author details were also in the commit (http://drupal.org/node/1146430). Cheers!

kostajh’s picture

Version: 6.x-2.x-dev » 7.x-2.x-dev
Status: Needs review » Fixed

Committed to 6.x-2.x: 036cc66f9 and 7.x-2.x: c856fc14778. Thanks for the patches!

rjacobs’s picture

Thanks Kosta for giving this such quick attention!

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.