php base64encode 长度,base64_encode

PHP源码阅读笔记三十八:base64_encode实现

【什么是base64编码】

Base64是一种使用64基的位置计数法。它使用2的最大次方来代表仅可打印的ASCII 字符。这使它可用来作为电子邮件的传输编码。在Base64中的变量使用字符A-Z、a-z和0-9 ,这样共有62个字符,用来作为开始的64个数字,最后两个用来作为数字的符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后binhex的版本使用不同的64字符集来代表6个二进制数字,但是它们不叫Base64。

【base64编码产生的历史原因】

在Email的传送过程中,由于历史原因,Email只被允许传送ASCII字符,即一个8位字节的低7位。因此,如果您发送了一封带有非ASCII字符(即字节的最高位是1)的Email通过有”历史问题“的网关时就可能会出现问题。网关可能会把最高位置为0!由于以上原因,产生了Base64编码。

【base64_encode的PHP内部实现】

base64_encode是PHP的标准函数,它存在于标准扩展中,在ext/standard/base64.c 210行,以标准的PHP_FUNCTION(base64_encode)实现。如下所示代码:

/* {{{ proto string base64_encode(string str)

Encodes string using MIME base64 algorithm */

PHP_FUNCTION(base64_encode)

{

char *str;

unsigned char *result;

int str_len, ret_length;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {

return;

}

result = php_base64_encode((unsigned char*)str, str_len, &ret_length);

if (result != NULL) {

RETVAL_STRINGL((char*)result, ret_length, 0);

} else {

RETURN_FALSE;

}

}

/* }}} */

第218行 函数的参数输入,base64_encode仅有一个参数,字符串数据类型;

第221行 调用php_base64_encode函数实现base64编码;

第222~226行 返回编码后的值,如果编码成功,返回编码后的字符串,如果失败返回FALSE

[PHP_FUNCTION(base64_encode) -> php_base64_encode()]

PHPAPI unsigned char *php_base64_encode(const unsigned char *str, int length, int *ret_length) /* {{{ */

{

const unsigned char *current = str;

unsigned char *p;

unsigned char *result;

if ((length + 2) < 0 || ((length + 2) / 3) >= (1 << (sizeof(int) * 8 - 2))) {

if (ret_length != NULL) {

*ret_length = 0;

}

return NULL;

}

result = (unsigned char *)safe_emalloc(((length + 2) / 3) * 4, sizeof(char), 1);

p = result;

while (length > 2) { /* keep going until we have less than 24 bits */

*p++ = base64_table[current[0] >> 2];

*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];

*p++ = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)];

*p++ = base64_table[current[2] & 0x3f];

current += 3;

length -= 3; /* we just handle 3 octets of data */

}

/* now deal with the tail end of things */

if (length != 0) {

*p++ = base64_table[current[0] >> 2];

if (length > 1) {

*p++ = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)];

*p++ = base64_table[(current[1] & 0x0f) << 2];

*p++ = base64_pad;

} else {

*p++ = base64_table[(current[0] & 0x03) << 4];

*p++ = base64_pad;

*p++ = base64_pad;

}

}

if (ret_length != NULL) {

*ret_length = (int)(p - result);

}

*p = '\0';

return result;

}

/* }}} */

第62~67行 输入判断,程序的健壮性处理,如果长度小于-2,或者长度大于2的(机器的int型长度 * 8 – 2)次方

第69行 按需分配内存

第72~80行 处理所给字符串的能被3整除的部分,在这里需要说明的是Base64编码要求把3个8位字节(3*8=24)转化为4个6位的字节(4*6=24),之后在6位的前面补两个0,形成8位一个字节的形式。

第83~94行 处理以3个字节划分后剩余的数据,分成只有一个字节,和两个字节的情况,分别在其后面添加一个或两个base64_pad,在这里base64_pad定义为:static const char base64_pad = ‘=’;

最后是添加’\0′,返回结果

【base64的URL应用】

Base64编码可用于在HTTP环境下传递较长的标识信息。例如,在Java持久化系统Hibernate中,就采用了Base64来将一个较长的唯一标识符(一般为128-bit的UUID)编码为一个字符串,用作HTTP表单和HTTP GET URL中的参数。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码不仅比较简短,同时也具有不可读性,即所编码的数据不会被人用肉眼所直接看到。

然而,标准的Base64并不适合直接放在URL里传输,因为URL编码器会把标准Base64中的「/」和「+」字符变为形如「%XX」的形式,而这些「%」号在存入数据库时还需要再进行转换,因为ANSI SQL中已将「%」号用作通配符。

为解决此问题,可采用一种用于URL的改进Base64编码,它不在末尾填充’=’号,并将标准Base64中的「+」和「/」分别改成了「*」和「-」,这样就免去了在URL编解码和数据库存储时所要作的转换,避免了编码信息长度在此过程中的增加,并统一了数据库、表单等处对象标识符的格式。

另有一种用于正则表达式的改进Base64变种,它将「+」和「/」改成了「!」和「-」,因为「+」,「*」以及前面在IRCu中用到的「[」和「]」在正则表达式中都可能具有特殊含义。

此外还有一些变种,它们将「+/」改为「_-」或「._」(用作编程语言中的标识符名称)或「.-」(用于XML中的Nmtoken)甚至「_:」(用于XML中的Name)。

以上部分来源于维基百科http://zh.wikipedia.org/zh/Base64

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值