[TIMOB-9111] TiAPI: Ti.Utils.base64encode behaves different between Android and iOS/Android
GitHub Issue | n/a |
Type | Bug |
Priority | High |
Status | Closed |
Resolution | Fixed |
Resolution Date | 2017-11-15T20:47:31.000+0000 |
Affected Version/s | Release 2.0.1, Release 3.1.0, Release 3.2.0 |
Fix Version/s | Release 7.0.0 |
Components | iOS |
Labels | SupportTeam, core, parity |
Reporter | Varun Joshi |
Assignee | Hans Knöchel |
Created | 2012-05-11T12:28:30.000+0000 |
Updated | 2017-11-17T21:45:59.000+0000 |
Description
Problem
The result of Ti.Utils.base64encode is different between iOS and Android. On iOS there are newline characters included when the string is long enough, on Android the newline characters are stripped out (which is the correct way to do base64 UTF8 encoding). Please see the attached screenshot explaining the issue.
Sample Code
{noformat}
(function() {
var win = Ti.UI.createWindow({backgroundColor:'white'});
win.open();
var shortString = 'ABCDEFGHIJ1234567890ABCDEFGHIJ12|psndemo2|abcd:1';
var longString = 'ABCDEFGHIJ1234567890ABCDEFGHIJ12|psndemo2|abcd:12345678901234567890';
var tiBase64ShortResult = Ti.Utils.base64encode(shortString);
var tiBase64LongResult = Ti.Utils.base64encode(longString);
tiBase64ShortResult = String(tiBase64ShortResult);
tiBase64LongResult = String(tiBase64LongResult);
// BUG #2: Run this code in iOS and Android and compare the results
// On iOS we get newline characters. On Android the newline characters are stripped out.
// The correct behavior for UTF8 base64 encoding is to strip out the newline characters.
// Android's implementation is correct.
tiBase64ShortResult = tiBase64ShortResult.replace(/\r\n/g,"***NEWLINE***");
tiBase64LongResult = tiBase64LongResult.replace(/\r\n/g,"***NEWLINE***");
var alertDialog = Titanium.UI.createAlertDialog(
{
title: 'Result',
message: 'short: ' + tiBase64ShortResult + '\nlong: ' + tiBase64LongResult, buttonNames: ['OK','Cancel']
});
alertDialog.show();
})();
{noformat}
Attachments
Could be because of the problem mentioned here http://developer.appcelerator.com/question/120731/xhr-authentication-with-restful-api "It's also important to note that Titanium.Utils.base64encode() adds line breaks every 72 characters (bug?)"
Issue reproduces Tested with Titanium Studio, build: 3.0.1.201212181159 Titanium SDK version: 3.1.0 Titanium SDK version: 3.0.2 iOS iPhone Simulator: iOS SDK version: 6.0
Can we get this scheduled please? After verifying newlines indeed shouldn't be included in base64encoded data, all we need to do is remove these here: https://github.com/appcelerator/titanium_mobile/blob/415bd6c66dcc55b1a59a59574f3babd3c3a84ede/iphone/Classes/Base64Transcoder.c#L132-L136 Also see: * http://stackoverflow.com/a/20065991/4626813 * http://stackoverflow.com/a/4680044/4626813 * https://en.wikipedia.org/wiki/Base64#Implementations_and_history Seems like it depends on the implementation. Perhaps we should make it an option.
BUMP! I've wasted 8+ hours only to find out this is the issue! HALP!
PR: https://github.com/appcelerator/titanium_mobile/pull/7976 Demo Code:
What is the expected value of the demo above? And are the results going to be the same on both Android and iOS?
There should just be no more new lines added redundantly, yes I believe they should be. There is more information available regarding the return values on the PR.
I'm saying that you should include the expected value inside the demo so when QE test it, they know what to expect, and if somehow they get a different value, then they would know its a bug.
[~apetkov] What's the status of this?
I posted some discussion about this on the PR, but I wanted to summarize here: - I think if anything, the fix should be to Android to default to adding newlines to split the output up. There are a number of uses/specs for base64: - https://tools.ietf.org/html/rfc4648#page-3 - https://en.wikipedia.org/wiki/Base64#Variants_summary_table Some of those specs *require* max line lengths (specifically 76 or 64 characters max per line). iOS and Windows both default to adding newlines to break up the output. So really, Android is the odd one out in comparison. Or, I suppose we can choose to default to no newlines, but would need to change both iOS and Windows. - I think we should modify the base64 method to take a second optional Dictionary argument to control behavior like this. For this who need a specific line length, or want to turn off newlines, or use different padding characters or characters for indices 62/63 - so that they could match the listed specs at https://en.wikipedia.org/wiki/Base64#Variants_summary_table Android's base64 does have some options around some of this: https://developer.android.com/reference/android/util/Base64.html Basically it looks like the defaults for encoding should hopefully be the options that'd work across most applications: max 76-char lines, use CRLF to break lines, use '=' for padding character, use '+' and '/' for indices 62 and 63. Then we could add options for: no newlines, URL safe chars ('-' and '_' for 62/63), etc.
Moving to 7.0.0 since this will be a (minor) breaking change on iOS and Windows. We will remove the \n characters to align with modern conversions. It will also eliminate possible issues with using those strings in the web-view (especially Ti.WKWebView).
PR (titanium_verify/master): https://github.com/appcelerator/titanium_verify/pull/25 PR (titanium_mobile/master): https://github.com/appcelerator/titanium_mobile/pull/9288 Test-case (
encodedFile.txt
is attached:Cloned this for Windows: TIMOB-25513 with fixVersion:none since I don't think we can slip this in to Windows within 7.0.0 time frame.
FR passed. [~kiguchi] thanks for creating the ticket for Windows. Currently looking into unit test issues.
Verified in SDK build 7.0.0.v20171117124508