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