118 lines
4.3 KiB
Mathematica
118 lines
4.3 KiB
Mathematica
|
function y = base64decode(x, outfname, alg)
|
||
|
%BASE64DECODE Perform base64 decoding on a string.
|
||
|
%
|
||
|
% INPUT:
|
||
|
% x - block of data to be decoded. Can be a string or a numeric
|
||
|
% vector containing integers in the range 0-255. Any character
|
||
|
% not part of the 65-character base64 subset set is silently
|
||
|
% ignored. Characters occuring after a '=' padding character are
|
||
|
% never decoded. If the length of the string to decode (after
|
||
|
% ignoring non-base64 chars) is not a multiple of 4, then a
|
||
|
% warning is generated.
|
||
|
%
|
||
|
% outfname - if provided the binary date from decoded string will be
|
||
|
% saved into a file. Since Base64 coding is often used to embbed
|
||
|
% binary data in xml files, this option can be used to extract and
|
||
|
% save them.
|
||
|
%
|
||
|
% alg - Algorithm to use: can take values 'java' or 'matlab'. Optional
|
||
|
% variable defaulting to 'java' which is a little faster. If
|
||
|
% 'java' is chosen than core of the code is performed by a call to
|
||
|
% a java library. Optionally all operations can be performed using
|
||
|
% matleb code.
|
||
|
%
|
||
|
% OUTPUT:
|
||
|
% y - array of binary data returned as uint8
|
||
|
%
|
||
|
% This function is used to decode strings from the Base64 encoding specified
|
||
|
% in RFC 2045 - MIME (Multipurpose Internet Mail Extensions). The Base64
|
||
|
% encoding is designed to represent arbitrary sequences of octets in a form
|
||
|
% that need not be humanly readable. A 65-character subset ([A-Za-z0-9+/=])
|
||
|
% of US-ASCII is used, enabling 6 bits to be represented per printable
|
||
|
% character.
|
||
|
%
|
||
|
% See also BASE64ENCODE.
|
||
|
%
|
||
|
% Written by Jarek Tuszynski, SAIC, jaroslaw.w.tuszynski_at_saic.com
|
||
|
%
|
||
|
% Matlab version based on 2004 code by Peter J. Acklam
|
||
|
% E-mail: pjacklam@online.no
|
||
|
% URL: http://home.online.no/~pjacklam
|
||
|
% http://home.online.no/~pjacklam/matlab/software/util/datautil/base64encode.m
|
||
|
|
||
|
if nargin<3, alg='java'; end
|
||
|
if nargin<2, outfname=''; end
|
||
|
|
||
|
%% if x happen to be a filename than read the file
|
||
|
if (numel(x)<256)
|
||
|
if (exist(x, 'file')==2)
|
||
|
fid = fopen(x,'rb');
|
||
|
x = fread(fid, 'uint8');
|
||
|
fclose(fid);
|
||
|
end
|
||
|
end
|
||
|
x = uint8(x(:)); % unify format
|
||
|
|
||
|
%% Perform conversion
|
||
|
switch (alg)
|
||
|
case 'java'
|
||
|
base64 = org.apache.commons.codec.binary.Base64;
|
||
|
y = base64.decode(x);
|
||
|
y = mod(int16(y),256); % convert from int8 to uint8
|
||
|
case 'matlab'
|
||
|
%% Perform the mapping
|
||
|
% A-Z -> 0 - 25
|
||
|
% a-z -> 26 - 51
|
||
|
% 0-9 -> 52 - 61
|
||
|
% + - -> 62 '-' is URL_SAFE alternative
|
||
|
% / _ -> 63 '_' is URL_SAFE alternative
|
||
|
map = uint8(zeros(1,256)+65);
|
||
|
map(uint8(['A':'Z', 'a':'z', '0':'9', '+/=']))= 0:64;
|
||
|
map(uint8('-_'))= 62:63; % URL_SAFE alternatives
|
||
|
x = map(x); % mapping
|
||
|
|
||
|
x(x>64)=[]; % remove non-base64 chars
|
||
|
if rem(numel(x), 4)
|
||
|
warning('Length of base64 data not a multiple of 4; padding input.');
|
||
|
end
|
||
|
x(x==64)=[]; % remove padding characters
|
||
|
|
||
|
%% add padding and reshape
|
||
|
nebytes = length(x); % number of encoded bytes
|
||
|
nchunks = ceil(nebytes/4); % number of chunks/groups
|
||
|
if rem(nebytes, 4)>0
|
||
|
x(end+1 : 4*nchunks) = 0; % add padding
|
||
|
end
|
||
|
x = reshape(uint8(x), 4, nchunks);
|
||
|
y = repmat(uint8(0), 3, nchunks); % for the decoded data
|
||
|
|
||
|
%% Rearrange every 4 bytes into 3 bytes
|
||
|
% 00aaaaaa 00bbbbbb 00cccccc 00dddddd
|
||
|
% to form
|
||
|
% aaaaaabb bbbbcccc ccdddddd
|
||
|
y(1,:) = bitshift(x(1,:), 2); % 6 highest bits of y(1,:)
|
||
|
y(1,:) = bitor(y(1,:), bitshift(x(2,:), -4)); % 2 lowest bits of y(1,:)
|
||
|
y(2,:) = bitshift(x(2,:), 4); % 4 highest bits of y(2,:)
|
||
|
y(2,:) = bitor(y(2,:), bitshift(x(3,:), -2)); % 4 lowest bits of y(2,:)
|
||
|
y(3,:) = bitshift(x(3,:), 6); % 2 highest bits of y(3,:)
|
||
|
y(3,:) = bitor(y(3,:), x(4,:)); % 6 lowest bits of y(3,:)
|
||
|
|
||
|
%% remove extra padding
|
||
|
switch rem(nebytes, 4)
|
||
|
case 2
|
||
|
y = y(1:end-2);
|
||
|
case 3
|
||
|
y = y(1:end-1);
|
||
|
end
|
||
|
end
|
||
|
|
||
|
%% reshape to a row vector and make it a character array
|
||
|
y = uint8(reshape(y, 1, numel(y)));
|
||
|
|
||
|
%% save to file if needed
|
||
|
if ~isempty(outfname)
|
||
|
fid = fopen(outfname,'wb');
|
||
|
fwrite(fid, y, 'uint8');
|
||
|
fclose(fid);
|
||
|
end
|