Decode an base64 encoded string through php in javascript - php

The question
How can I decode a string with JavaScript that's encoded in php and maintain the "åäö" letters?
Overview of the problem
As the title states I'm trying to decode a base64 encoded string that I generate from my php code. It all works fine except for the letters "åäö" that the Swedish alphabet ends with.
Output exemple:
å ä ö Å Ä Ö => Ã¥ ä ö à à Ã
Code
The base64 JavaScript I'm using
/*
* Copyright (c) 2010 Nick Galbreath
* http://code.google.com/p/stringencoders/source/browse/#svn/trunk/javascript
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/* base64 encode/decode compatible with window.btoa/atob
*
* window.atob/btoa is a Firefox extension to convert binary data (the "b")
* to base64 (ascii, the "a").
*
* It is also found in Safari and Chrome. It is not available in IE.
*
* if (!window.btoa) window.btoa = base64.encode
* if (!window.atob) window.atob = base64.decode
*
* The original spec's for atob/btoa are a bit lacking
* https://developer.mozilla.org/en/DOM/window.atob
* https://developer.mozilla.org/en/DOM/window.btoa
*
* window.btoa and base64.encode takes a string where charCodeAt is [0,255]
* If any character is not [0,255], then an exception is thrown.
*
* window.atob and base64.decode take a base64-encoded string
* If the input length is not a multiple of 4, or contains invalid characters
* then an exception is thrown.
*/
base64 = {};
base64.PADCHAR = '=';
base64.ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
base64.getbyte64 = function(s,i) {
// This is oddly fast, except on Chrome/V8.
// Minimal or no improvement in performance by using a
// object with properties mapping chars to value (eg. 'A': 0)
var idx = base64.ALPHA.indexOf(s.charAt(i));
if (idx == -1) {
throw "Cannot decode base64";
}
return idx;
}
base64.decode = function(s) {
// convert to string
s = "" + s;
var getbyte64 = base64.getbyte64;
var pads, i, b10;
var imax = s.length
if (imax == 0) {
return s;
}
if (imax % 4 != 0) {
throw "Cannot decode base64";
}
pads = 0
if (s.charAt(imax -1) == base64.PADCHAR) {
pads = 1;
if (s.charAt(imax -2) == base64.PADCHAR) {
pads = 2;
}
// either way, we want to ignore this last block
imax -= 4;
}
var x = [];
for (i = 0; i < imax; i += 4) {
b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) |
(getbyte64(s,i+2) << 6) | getbyte64(s,i+3);
x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff, b10 & 0xff));
}
switch (pads) {
case 1:
b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | (getbyte64(s,i+2) << 6)
x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff));
break;
case 2:
b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12);
x.push(String.fromCharCode(b10 >> 16));
break;
}
return x.join('');
}
base64.getbyte = function(s,i) {
var x = s.charCodeAt(i);
if (x > 255) {
throw "INVALID_CHARACTER_ERR: DOM Exception 5";
}
return x;
}
base64.encode = function(s) {
if (arguments.length != 1) {
throw "SyntaxError: Not enough arguments";
}
var padchar = base64.PADCHAR;
var alpha = base64.ALPHA;
var getbyte = base64.getbyte;
var i, b10;
var x = [];
// convert to string
s = "" + s;
var imax = s.length - s.length % 3;
if (s.length == 0) {
return s;
}
for (i = 0; i < imax; i += 3) {
b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8) | getbyte(s,i+2);
x.push(alpha.charAt(b10 >> 18));
x.push(alpha.charAt((b10 >> 12) & 0x3F));
x.push(alpha.charAt((b10 >> 6) & 0x3f));
x.push(alpha.charAt(b10 & 0x3f));
}
switch (s.length - imax) {
case 1:
b10 = getbyte(s,i) << 16;
x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
padchar + padchar);
break;
case 2:
b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8);
x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
alpha.charAt((b10 >> 6) & 0x3f) + padchar);
break;
}
return x.join('');
}
The implementation
<script type="text/javascript">
document.write(
base64.decode( '<?php echo base64_encode( "å ä ö Å Ä Ö" ); ?>' ) );
</script>
Edit
The script I found that worked:
(someone asked me for this, so here it is)
var Base64 =
{
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode : function (input)
{
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},
// public method for decoding
decode : function (input)
{
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = Base64._utf8_decode(output);
return output;
},
// private method for UTF-8 encoding
_utf8_encode : function (string)
{
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// private method for UTF-8 decoding
_utf8_decode : function (utftext)
{
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}

Looks like a character encoding problem, make sure all you files are using the same encoding (UTF-8?) even you JavaScript files.
If not try searching to see if others have experienced the same problem, most likely with those special characters. (I'm from Norway, so I know how it is with those damn characters ;)
If this don't solve your problem, try another JavaScript base64 decoder.

You might give this a shot to see if it solves your problem:
http://phpjs.org/

Related

Convert 6 array-bytes to int64 using PHP

I'm reverse engineering a javascript script to PHP and there are many functions that convert:
6 array bytes of [224, 221, 199, 147, 195, 47]
and output that to 1632933900000 (which is timestamp, Int64)
Can you help me how to pack/unpack those bytes as above to the final integer using PHP ?
Samples:
[224, 221, 199, 147, 195, 47] gets to 1632933900000
[224, 143, 228, 137, 198, 47]
gets to 1633718700000
ADDITIONAL INFO:
The javascript code is very long (it was obfuscated). I just know for certain that it is placed within 6 bytes.
NEXT UPDATE...
It goes to this function (this.buf is array-bytes):
function u() {
var e = new a(0, 0),
t = 0;
if (!(this.len - this.pos > 4)) {
for (; t < 3; ++t) {
if (this.pos >= this.len) throw s(this);
if (e.lo = (e.lo | (127 & this.buf[this.pos]) << 7 * t) >>> 0, this.buf[this.pos++] < 128) return e
}
return e.lo = (e.lo | (127 & this.buf[this.pos++]) << 7 * t) >>> 0, e
}
for (; t < 4; ++t)
if (e.lo = (e.lo | (127 & this.buf[this.pos]) << 7 * t) >>> 0, this.buf[this.pos++] < 128) return e;
if (e.lo = (e.lo | (127 & this.buf[this.pos]) << 28) >>> 0, e.hi = (e.hi | (127 & this.buf[this.pos]) >> 4) >>> 0, this.buf[this.pos++] < 128) return e;
if (t = 0, this.len - this.pos > 4) {
for (; t < 5; ++t)
if (e.hi = (e.hi | (127 & this.buf[this.pos]) << 7 * t + 3) >>> 0, this.buf[this.pos++] < 128) return e
} else
for (; t < 5; ++t) {
if (this.pos >= this.len) throw s(this);
if (e.hi = (e.hi | (127 & this.buf[this.pos]) << 7 * t + 3) >>> 0, this.buf[this.pos++] < 128) return e
}
throw Error("invalid varint encoding")
}
And then it has [hi and low] numbers and this gets the timestamp:
o.prototype.toNumber = function(e) {
if (!e && this.hi >>> 31) {
var t = 1 + ~this.lo >>> 0,
n = ~this.hi >>> 0;
return t || (n = n + 1 >>> 0), -(t + 4294967296 * n)
}
return this.lo + 4294967296 * this.hi
}
224 221 199 147 195 47 is the decimal representation of E0 DD C7 93 C3 2F ... which is 247243140743983 in decimal. Maybe not the whole dword is the timestamp ...for comparision: 01 7C 32 71 EE E0 or 61 54 98 0C. One can already notice by the first digit, how far off this approach is.
That number in JS might be of type BigInt:
BigInt("0x017C3271EEE0")
But BigInt("0xE0DDC793C32F") still gives 247243140743983.
Just to complete this answer I used following stuff, but I have absolutely no clue what it does :D
<?php
function int64_helper($obj)
{
$e = (object) ['lo' => 0, 'hi' => 0];
if (!($obj->len - $obj->pos > 4)) {
for ($i = 0; $i < 3; $i++) {
if ($obj->pos >= $obj->len) throw new Exception('ERROR RANGE');
$e->lo = rrr($e->lo | ((127 & $obj->buf[$obj->pos]) << (7 * $i)), 0);
if ($obj->buf[$obj->pos++] < 128) return $e;
}
$e->lo = rrr($e->lo | ((127 & $obj->buf[$obj->pos++]) << (7 * $i)), 0);
return $e;
}
for ($i = 0; $i < 4; $i++) {
$e->lo = rrr($e->lo | ((127 & $obj->buf[$obj->pos]) << (7 * $i)), 0);
if ($obj->buf[$obj->pos++] < 128) return $e;
}
$e->lo = rrr(($e->lo | ((127 & $obj->buf[$obj->pos]) << 28)), 0);
$e->hi = rrr(($e->hi | rr((127 & $obj->buf[$obj->pos]), 4)), 0);
if ($obj->buf[$obj->pos++] < 128) {
return $e;
}
if ($obj->len - $obj->pos > 4) {
for ($i = 0; $i < 5; $i++) {
$e->hi = rrr($e->hi | ((127 & $obj->buf[$obj->pos]) << (7 * $i) + 3), 0);
if ($obj->buf[$obj->pos++] < 128) return $e;
}
}
else {
for ($i = 0; $i < 5; $i++) {
if ($obj->pos >= $obj->len) throw new Exception('ERROR RANGE');
$e->hi = rrr($e->hi | ((127 & $obj->buf[$obj->pos]) << (7 * $i) + 3), 0);
if ($obj->buf[$obj->pos++] < 128) return $e;
}
}
throw new Exception("invalid timestamp encoding");
}
/**
* Date time
*/
function int64($obj)
{
$e = int64_helper($obj);
$mst = $e->lo + 4294967296 * $e->hi;
$t = substr($mst, 0, -3); // poslední 3 nuly dávám pryč
$s = date("Y-m-d H:i:s", $t); // prague timezone
return $s;
}
/**
* The >>> javascript operator in php x86_64
* Usage: -1149025787 >>> 0 ---> rrr(-1149025787, 0) === 3145941509
* #return int
*/
function rrr($v, $n)
{
return ($v & 0xFFFFFFFF) >> ($n & 0x1F);
}
/**
* The >> javascript operator in php x86_64
* #return int
*/
function rr($v, $n)
{
return ($v & 0x80000000 ? $v | 0xFFFFFFFF00000000 : $v & 0xFFFFFFFF) >> ($n & 0x1F);
}
/**
* The << javascript operator in php x86_64
* #return int
*/
function ll($v, $n)
{
return ($t = ($v & 0xFFFFFFFF) << ($n & 0x1F)) & 0x80000000 ? $t | 0xFFFFFFFF00000000 : $t & 0xFFFFFFFF;
}

Websocket: How to encode a text to send to a client, in C

I'm trying to develop a function for encode a text in a correct format of websocket data send. this is a function in PHP but I can't translate this in C language.
private function encode($text) {
// 0x1 text frame (FIN + opcode)
$b1 = 0x80 | (0x1 & 0x0f);
$length = strlen($text);
if($length <= 125)
$header = pack('CC', $b1, $length);
elseif($length > 125 && $length < 65536)
$header = pack('CCS', $b1, 126, $length);
elseif($length >= 65536)
$header = pack('CCN', $b1, 127, $length);
return $header.$text;
}
There's less need for bureaucracy, so it's much simpler to implement. Normally you expect the caller to provide the output buffer and the text size, so let's do that.
Also, be extra careful with the endianness, your second use of pack in that PHP code should be with 'CCn' instead of 'CCS'.
Example implementation:
static char *hdr_fill(char *buf, unsigned int hlen, size_t plen)
{
*buf++ = 0x81; /* b1 */
switch (hlen) {
case 6:
*buf++ = 127;
break;
case 4:
*buf++ = 126;
}
/* Store length in big endian order */
switch (hlen) {
case 6:
*buf++ = plen >> 24;
*buf++ = plen >> 16;
case 4:
*buf++ = plen >> 8;
case 2:
*buf++ = plen;
}
return buf;
}
size_t encode(char *buf, size_t bufsize, const char *text, size_t len)
{
const unsigned int hdrlen = len > 65535 ? 6 : (len > 255 ? 4 : 2);
if (bufsize < hdrlen + len)
return 0;
buf = hdr_fill(buf, hdrlen, len);
memcpy(buf, text, len);
return hdrlen + len;
}
For convenience it returns the result's size. You will need at least <stddef.h> (unless you replace size_t) and <string.h>.
However, you may want to use a scatter-gather approach instead, as it avoids the copying. In that case you just need to build the header and adjust it's vector. Also, IMO it's more elegant:
int setup_header(struct iovec *v, int n)
{
/* We expect a valid buffer in v[0], and the payload in v[1+] */
if (n < 2 || v[0]->iov_len < 6)
return -1;
size_t len = v[1]->iov_len;
for (int i = 2; i < n; i++)
len += v[n]->iov_len;
const unsigned int hdrlen = len > 65535 ? 6 : (len > 255 ? 4 : 2);
v[0]->iov_len = hdrlen;
hdr_fill(v[0]->iov_base, hdrlen, len);
return 0;
}
In this case the return value is zero if successful. For this one you need <sys/uio.h> or equivalent.

Convert Int into 4 Byte String in PHP

I need to convert an unsigned integer into a 4 byte string to send on a socket.
I have the following code and it works, but it feels... disgusting.
/**
* #param $int
* #return string
*/
function intToFourByteString( $int ) {
$four = floor($int / pow(2, 24));
$int = $int - ($four * pow(2, 24));
$three = floor($int / pow(2, 16));
$int = $int - ($three * pow(2, 16));
$two = floor($int / pow(2, 8));
$int = $int - ($two * pow(2, 8));
$one = $int;
return chr($four) . chr($three) . chr($two) . chr($one);
}
My friend who uses C says I should be able to do this with bitshifts but I don't know how and he isn't familiar enough with PHP to be helpful. Any help would be appreciated.
To do the reverse I already have the following code
/**
* #param $string
* #return int
*/
function fourByteStringToInt( $string ) {
if( strlen($string) != 4 ) {
throw new \InvalidArgumentException('String to parse must be 4 bytes exactly');
}
return (ord($string[0]) << 24) + (ord($string[1]) << 16) + (ord($string[2]) << 8) + ord($string[3]);
}
This is actually as simple as
$str = pack('N', $int);
see pack. And the reverse:
$int = unpack('N', $str)[1];
If you're curious how to do packing using bit shifts, it goes like this:
function intToFourByteString( $int ) {
return
chr($int >> 24 & 0xFF).
chr($int >> 16 & 0xFF).
chr($int >> 8 & 0xFF).
chr($int >> 0 & 0xFF);
}
Basically, shift eight bits each time and mask with 0xFF (=255) to remove high-order bits.

javascript base64 encode and non-ascii symbols [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
I need get base64 encoded string in javascript, ( input string may contains non ascii symbols )
There is some good solution ?
If you work with Unicode in the string you finally encode with Base64, I'd suggest to use the following script proposed by WebToolkit.info. Script is fully compatible with UTF-8 encoding.
/**
*
* Base64 encode / decode
* http://www.webtoolkit.info/
*
**/
var Base64 = {
// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = Base64._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
}
return output;
},
// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
while (i < input.length) {
enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
output = output + String.fromCharCode(chr1);
if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}
}
output = Base64._utf8_decode(output);
return output;
},
// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
},
// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;
while ( i < utftext.length ) {
c = utftext.charCodeAt(i);
if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) && (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}
}
return string;
}
}
DEMO: http://www.webtoolkit.info/demo/javascript-base64
There is no language default solution to get a string to be base64. You'll have to write your own function, or steal this one:
http://ntt.cc/2008/01/19/base64-encoder-decoder-with-javascript.html

NSString en/decode base64

I am trying to make a equilvant of these php functions to encrype/decrypt in objective c but with no luck so far.
I counld't find any base64_en/decode methods in obj-c, is there any?
function encrypt($string, $key) {
$result = '';
 for($i = 0; $i < strlen($string); $i++) {
$char = substr($string, $i, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char) + ord($keychar));
$result .= $char;
 }

return base64_encode($result);
}
function decrypt($string, $key) {
$result = '';
$string = base64_decode($string);
for($i = 0; $i < strlen($string); $i++) {
$char = substr($string, $i, 1);
$keychar = substr($key, ($i % strlen($key))-1, 1);
$char = chr(ord($char) - ord($keychar));
$result.=$char;
}
return $result;
}
Ty already!
Check out this category I use for this very task, it's an NSString category for converting strings to md5, base64 etc...
https://gist.github.com/3907443
From NSString to NSData:
+ (NSString *)encodeBase64WithString:(NSString *)strData {
return [NSString encodeBase64WithData:[strData dataUsingEncoding:NSUTF8StringEncoding]];
}
Encode from NSData:
+ (NSString *)encodeBase64WithData:(NSData *)objData {
const unsigned char * objRawData = [objData bytes];
char * objPointer;
char * strResult;
// Get the Raw Data length and ensure we actually have data
int intLength = [objData length];
if (intLength == 0) return nil;
// Setup the String-based Result placeholder and pointer within that placeholder
strResult = (char *)calloc(((intLength + 2) / 3) * 4, sizeof(char));
objPointer = strResult;
// Iterate through everything
while (intLength > 2) { // keep going until we have less than 24 bits
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
*objPointer++ = _base64EncodingTable[((objRawData[1] & 0x0f) << 2) + (objRawData[2] >> 6)];
*objPointer++ = _base64EncodingTable[objRawData[2] & 0x3f];
// we just handled 3 octets (24 bits) of data
objRawData += 3;
intLength -= 3;
}
// now deal with the tail end of things
if (intLength != 0) {
*objPointer++ = _base64EncodingTable[objRawData[0] >> 2];
if (intLength > 1) {
*objPointer++ = _base64EncodingTable[((objRawData[0] & 0x03) << 4) + (objRawData[1] >> 4)];
*objPointer++ = _base64EncodingTable[(objRawData[1] & 0x0f) << 2];
*objPointer++ = '=';
} else {
*objPointer++ = _base64EncodingTable[(objRawData[0] & 0x03) << 4];
*objPointer++ = '=';
*objPointer++ = '=';
}
}
// Terminate the string-based result
*objPointer = '\0';
// Return the results as an NSString object
return [NSString stringWithCString:strResult encoding:NSASCIIStringEncoding];
}
Decode:
+ (NSData *)decodeBase64WithString:(NSString *)strBase64 {
const char * objPointer = [strBase64 cStringUsingEncoding:NSASCIIStringEncoding];
int intLength = strlen(objPointer);
int intCurrent;
int i = 0, j = 0, k;
unsigned char * objResult;
objResult = calloc(intLength, sizeof(char));
// Run through the whole string, converting as we go
while ( ((intCurrent = *objPointer++) != '\0') && (intLength-- > 0) ) {
if (intCurrent == '=') {
if (*objPointer != '=' && ((i % 4) == 1)) {// || (intLength > 0)) {
// the padding character is invalid at this point -- so this entire string is invalid
free(objResult);
return nil;
}
continue;
}
intCurrent = _base64DecodingTable[intCurrent];
if (intCurrent == -1) {
// we're at a whitespace -- simply skip over
continue;
} else if (intCurrent == -2) {
// we're at an invalid character
free(objResult);
return nil;
}
switch (i % 4) {
case 0:
objResult[j] = intCurrent << 2;
break;
case 1:
objResult[j++] |= intCurrent >> 4;
objResult[j] = (intCurrent & 0x0f) << 4;
break;
case 2:
objResult[j++] |= intCurrent >>2;
objResult[j] = (intCurrent & 0x03) << 6;
break;
case 3:
objResult[j++] |= intCurrent;
break;
}
i++;
}
// mop things up if we ended on a boundary
k = j;
if (intCurrent == '=') {
switch (i % 4) {
case 1:
// Invalid state
free(objResult);
return nil;
case 2:
k++;
// flow through
case 3:
objResult[k] = 0;
}
}
// Cleanup and setup the return NSData
NSData * objData = [[[NSData alloc] initWithBytes:objResult length:j] autorelease];
free(objResult);
return objData;
}

Categories