{ "id": "62243", "key": "TIMOB-1611", "fields": { "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false }, "project": { "id": "10153", "key": "TIMOB", "name": "Titanium SDK/CLI", "projectCategory": { "id": "10100", "description": "Titanium and related SDKs used in application development", "name": "Client" } }, "fixVersions": [ { "id": "11331", "description": "", "name": "Release 1.8.0", "archived": true, "released": true, "releaseDate": "2011-10-31" } ], "resolution": { "id": "3", "description": "The problem is a duplicate of an existing issue.", "name": "Duplicate" }, "resolutiondate": "2011-12-29T18:32:32.000+0000", "created": "2011-04-15T02:57:18.000+0000", "priority": { "name": "Trivial", "id": "5" }, "labels": [ "blob", "defect", "ios", "parity" ], "versions": [ { "id": "11570", "description": "", "name": "Release 1.7.2", "archived": true, "released": true, "releaseDate": "2011-07-21" } ], "issuelinks": [ { "id": "14405", "type": { "id": "10002", "name": "Duplicate", "inward": "is duplicated by", "outward": "duplicates" }, "outwardIssue": { "id": "83026", "key": "TIMOB-6280", "fields": { "summary": "iOS: base64 encoding inconsistent for iOS simluators and iOS devices ", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "priority": { "name": "High", "id": "2" }, "issuetype": { "id": "1", "description": "A problem which impairs or prevents the functions of the product.", "name": "Bug", "subtask": false } } } } ], "assignee": { "name": "stephentramer", "key": "stephentramer", "displayName": "Stephen Tramer", "active": true, "timeZone": "America/Los_Angeles" }, "updated": "2017-03-24T18:31:33.000+0000", "status": { "description": "The issue is considered finished, the resolution is correct. Issues which are closed can be reopened.", "name": "Closed", "id": "6", "statusCategory": { "id": 3, "key": "done", "colorName": "green", "name": "Done" } }, "components": [ { "id": "10206", "name": "iOS", "description": "iOS Platform" } ], "description": "{html}

This was already addressed for android as lighthouse ticket\r\n#1604, below are Bill's original notes from the\r\nbug.

\r\n

You cannot use Titanium.Utils.base64encode &\r\nTitanium.Utils.base64decode successfully to round-trip the encoding\r\n/ decoding of a blob. In other words, you don't get back the same\r\nset of bytes that you originally started with.

\r\n

Failcase app.js (make sure you have KS_nav_ui.png in your\r\nResources folder; it's there by default with new projects):

\r\n

var win = Ti.UI.createWindow({fullscreen: true,\r\nexitOnClose:true});

\r\n

var file = Ti.Filesystem.getFile('KS_nav_ui.png');

\r\n

var blob1 = file.read();
\r\nvar base64 = Ti.Utils.base64encode(blob1);
\r\nvar blob2 = Ti.Utils.base64decode(base64);

\r\n

var thumbnail1 = Titanium.UI.createView({left: 0, top: 0, width:\r\n46, height: 43});
\r\nthumbnail1.backgroundImage = 'KS_nav_ui.png'; // the orig, which\r\nobviously works
\r\nvar thumbnail2 = Titanium.UI.createView({left: 56, top: 0, width:\r\n46, height: 43});
\r\nvar thumbnail3 = Titanium.UI.createView({left: 112, top: 0, width:\r\n46, height: 43});
\r\nwin.add(thumbnail1); win.add(thumbnail2); win.add(thumbnail3);

\r\n

var tempDir = Titanium.Filesystem.createTempDirectory();
\r\ntempDir.createDirectory();

\r\n

// Blob from original file var file1 =\r\nTitanium.Filesystem.getFile(tempDir.nativePath, 'file1.png');
\r\nfile1.write(blob1);
\r\nthumbnail2.backgroundImage = file1.nativePath;

\r\n

// Base64 encoded-then-decoded blob var file2 =\r\nTitanium.Filesystem.getFile(tempDir.nativePath, 'file2.png');
\r\nfile2.write(blob2);
\r\nthumbnail3.backgroundImage = file2.nativePath;

\r\n

win.open();
\r\nYou should see three identical images when that runs. Instead,\r\nyou'll see only two.

{html}", "attachment": [], "flagged": false, "summary": "iOS: base64 encoding/decoding of Blob cannot be round-tripped successfully", "creator": { "name": "thomashuelbert", "key": "thomashuelbert", "displayName": "Thomas Huelbert", "active": true, "timeZone": "America/Los_Angeles" }, "subtasks": [], "reporter": { "name": "thomashuelbert", "key": "thomashuelbert", "displayName": "Thomas Huelbert", "active": true, "timeZone": "America/Los_Angeles" }, "environment": null, "comment": { "comments": [ { "id": "126186", "author": { "name": "jamesdavidlow", "key": "jamesdavidlow", "displayName": "James David Low", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

Hi, I'm an end user of Titanium that had some trouble with this\nrecently.

\n

The problem on iPhone is that the TiBlob is converted to a\nString first using UtilsModule.convertToString grabbing the\nTiBlob.text field. If the TiBlob is an image or file you need to\nuse the TiBlob.data field.

\n

I managed to get it to work using the attached code. I figured\nit was better to use the TiBlob.data rather than TiBlob.text\nalways, as if you really must base64 encode a String from a blob\nyou can change your Javascript to Ti.Utils.base64encode(blob.text)\nand it will still encode it.

\n

-(TiBlob*)base64encode:(id)args {

\n
\nENSURE_SINGLE_ARG(args,NSObject);\nconst char *data;\nsize_t len;\nif ([args isKindOfClass:[NSString class]])\n{\n    data = [args UTF8String];\n    len = [args length];\n}\nelse if ([args isKindOfClass:[TiBlob class]])\n{\n    data = [[(TiBlob*)args data] bytes];\n    len = [[(TiBlob*)args data] length];\n}\nelse\n{\n    THROW_INVALID_ARG(@\"invalid type\");\n}\n\nsize_t outsize = EstimateBas64EncodedDataSize(len);\nchar *base64Result = malloc(sizeof(char)*outsize);\nsize_t theResultLength = outsize;\n\nbool result = Base64EncodeData(data, len, base64Result, &theResultLength);\nif (result)\n{\n    NSData *theData = [NSData dataWithBytes:base64Result length:theResultLength];\n    free(base64Result);\n    return [[[TiBlob alloc] initWithData:theData mimetype:@\"application/octet-stream\"] autorelease];\n}    \nfree(base64Result);\nreturn nil;\n
\n

}

{html}", "updateAuthor": { "name": "jamesdavidlow", "key": "jamesdavidlow", "displayName": "James David Low", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T02:57:19.000+0000", "updated": "2011-04-15T02:57:19.000+0000" }, { "id": "126187", "author": { "name": "jamesdavidlow", "key": "jamesdavidlow", "displayName": "James David Low", "active": true, "timeZone": "America/Los_Angeles" }, "body": "{html}

I also created this function because I wanted the TiBlob I\ncreated to be an Image with width/height attributes. Is it possible\nto
\n1) Add it to UtilsModule.m
\nor
\n2) Have an optional parameter that determines the type of TiBlob to\nreturn
\nor
\n3) Maybe even better have an TiBlob be able to create another\nTiBlob of type TiBlobTypeImage from the data within it. Maybe at\nthe same time you could provide a constructor in Javascript to let\nus create our own TiBlobs from our own data.

\n

-(TiBlob*)base64decodeImage:(id)args {

\n
\nENSURE_SINGLE_ARG(args,NSObject);\n\nNSString *str = [self convertToString:args];\n\nconst char *data = [str UTF8String];\nsize_t len = [str length];\n\nsize_t outsize = EstimateBas64DecodedDataSize(len);\nchar *base64Result = malloc(sizeof(char)*outsize);\nsize_t theResultLength = outsize;\n\nbool result = Base64DecodeData(data, len, base64Result, &theResultLength);\nif (result)\n{\n    NSData *theData = [NSData dataWithBytes:base64Result length:theResultLength];\n    free(base64Result);\n    return [[[TiBlob alloc] initWithImage:[UIImage imageWithData:theData]] autorelease];\n}    \nfree(base64Result);\nreturn nil;\n
\n

}

{html}", "updateAuthor": { "name": "jamesdavidlow", "key": "jamesdavidlow", "displayName": "James David Low", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-04-15T02:57:19.000+0000", "updated": "2011-04-15T02:57:19.000+0000" }, { "id": "169332", "author": { "name": "jamesdlow", "key": "jamesdlow", "displayName": "James David Low", "active": true, "timeZone": "Europe/London" }, "body": "Hi Reggie,\r\n\r\nThis problem isn't trivial its actually quite serious that it isn't able to do the round trip and makes it a bit unusable.\r\n\r\nI have a fully changed UtilsModule.m that has all the necessary changes:\r\n1) To make a round trip possible\r\n2) To return a image type TiBlob which has dimensions initiated.\r\n\r\nPlease contact me about this, I'd really like to get it sorted as I have to make changes to the Titanium SDK every time there's an issue.\r\n\r\nYou can use my email james.low @ onoko.com\r\nThanks,\r\nJames", "updateAuthor": { "name": "jamesdlow", "key": "jamesdlow", "displayName": "James David Low", "active": true, "timeZone": "Europe/London" }, "created": "2011-10-14T18:36:41.000+0000", "updated": "2011-10-14T18:36:41.000+0000" }, { "id": "171043", "author": { "name": "wluu", "key": "wluu", "displayName": "Wilson Luu", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Bug is not valid, does not reproduce in:\r\nTiMOB sdk version: 1.8.0.v20111031173855\r\nStudio version: 1.0.6.201110251616\r\nOS version: Mac OS X Lion\r\nDevices tested on: ipad 4.3.5\r\n\r\nNote: 1.7.2 still show this bug, 1.8.0.v20111031173855 fixes this bug", "updateAuthor": { "name": "wluu", "key": "wluu", "displayName": "Wilson Luu", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2011-11-01T09:58:47.000+0000", "updated": "2011-11-02T10:15:53.000+0000" }, { "id": "171192", "author": { "name": "rseagraves", "key": "rseagraves", "displayName": "Reggie Seagraves", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Parity check with Android implementation.", "updateAuthor": { "name": "rseagraves", "key": "rseagraves", "displayName": "Reggie Seagraves", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-11-02T10:01:57.000+0000", "updated": "2011-11-02T10:01:57.000+0000" }, { "id": "177675", "author": { "name": "stephentramer", "key": "stephentramer", "displayName": "Stephen Tramer", "active": true, "timeZone": "America/Los_Angeles" }, "body": "Duplicate of TIMOB-6280.", "updateAuthor": { "name": "stephentramer", "key": "stephentramer", "displayName": "Stephen Tramer", "active": true, "timeZone": "America/Los_Angeles" }, "created": "2011-12-29T18:32:32.000+0000", "updated": "2011-12-29T18:32:32.000+0000" }, { "id": "415683", "author": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "body": "Closing ticket as duplicate with reference to the linked issues.", "updateAuthor": { "name": "lmorris", "key": "lmorris", "displayName": "Lee Morris", "active": false, "timeZone": "America/Los_Angeles" }, "created": "2017-03-24T18:31:33.000+0000", "updated": "2017-03-24T18:31:33.000+0000" } ], "maxResults": 7, "total": 7, "startAt": 0 } } }