base64是广为使用的一种编码及解码方式, 通常用于网络传输和邮件传输中,使用base64可以将标点符号以及多字节文字等特殊字符编码以便传输,以下是base64 编码解码的objective-c代码, 可以用于desktop和iphone程序当中

头文件

?Download base64.h
1
2
3
4
5
6
7
#include <UIKit/UIKit.h>
 
extern size_t EstimateBas64EncodedDataSize(size_t inDataSize);
extern size_t EstimateBas64DecodedDataSize(size_t inDataSize);
 
extern bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize, BOOL wrapped);
extern bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize);

实现文件

?Download base64.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#include "Base64Transcoder.h"
 
#include <math.h>
 
const UInt8 kBase64EncodeTable[64] = {
	/*  0 */ 'A',	/*  1 */ 'B',	/*  2 */ 'C',	/*  3 */ 'D', 
	/*  4 */ 'E',	/*  5 */ 'F',	/*  6 */ 'G',	/*  7 */ 'H', 
	/*  8 */ 'I',	/*  9 */ 'J',	/* 10 */ 'K',	/* 11 */ 'L', 
	/* 12 */ 'M',	/* 13 */ 'N',	/* 14 */ 'O',	/* 15 */ 'P', 
	/* 16 */ 'Q',	/* 17 */ 'R',	/* 18 */ 'S',	/* 19 */ 'T', 
	/* 20 */ 'U',	/* 21 */ 'V',	/* 22 */ 'W',	/* 23 */ 'X', 
	/* 24 */ 'Y',	/* 25 */ 'Z',	/* 26 */ 'a',	/* 27 */ 'b', 
	/* 28 */ 'c',	/* 29 */ 'd',	/* 30 */ 'e',	/* 31 */ 'f', 
	/* 32 */ 'g',	/* 33 */ 'h',	/* 34 */ 'i',	/* 35 */ 'j', 
	/* 36 */ 'k',	/* 37 */ 'l',	/* 38 */ 'm',	/* 39 */ 'n', 
	/* 40 */ 'o',	/* 41 */ 'p',	/* 42 */ 'q',	/* 43 */ 'r', 
	/* 44 */ 's',	/* 45 */ 't',	/* 46 */ 'u',	/* 47 */ 'v', 
	/* 48 */ 'w',	/* 49 */ 'x',	/* 50 */ 'y',	/* 51 */ 'z', 
	/* 52 */ '0',	/* 53 */ '1',	/* 54 */ '2',	/* 55 */ '3', 
	/* 56 */ '4',	/* 57 */ '5',	/* 58 */ '6',	/* 59 */ '7', 
	/* 60 */ '8',	/* 61 */ '9',	/* 62 */ '+',	/* 63 */ '/'
};
 
/*
-1 = Base64 end of data marker.
-2 = White space (tabs, cr, lf, space)
-3 = Noise (all non whitespace, non-base64 characters) 
-4 = Dangerous noise
-5 = Illegal noise (null byte)
*/
 
const SInt8 kBase64DecodeTable[128] = {
	/* 0x00 */ -5, 	/* 0x01 */ -3, 	/* 0x02 */ -3, 	/* 0x03 */ -3,
	/* 0x04 */ -3, 	/* 0x05 */ -3, 	/* 0x06 */ -3, 	/* 0x07 */ -3,
	/* 0x08 */ -3, 	/* 0x09 */ -2, 	/* 0x0a */ -2, 	/* 0x0b */ -2,
	/* 0x0c */ -2, 	/* 0x0d */ -2, 	/* 0x0e */ -3, 	/* 0x0f */ -3,
	/* 0x10 */ -3, 	/* 0x11 */ -3, 	/* 0x12 */ -3, 	/* 0x13 */ -3,
	/* 0x14 */ -3, 	/* 0x15 */ -3, 	/* 0x16 */ -3, 	/* 0x17 */ -3,
	/* 0x18 */ -3, 	/* 0x19 */ -3, 	/* 0x1a */ -3, 	/* 0x1b */ -3,
	/* 0x1c */ -3, 	/* 0x1d */ -3, 	/* 0x1e */ -3, 	/* 0x1f */ -3,
	/* ' ' */ -2,	/* '!' */ -3,	/* '"' */ -3,	/* '#' */ -3,
	/* '$' */ -3,	/* '%' */ -3,	/* '&' */ -3,	/* ''' */ -3,
	/* '(' */ -3,	/* ')' */ -3,	/* '*' */ -3,	/* '+' */ 62,
	/* ',' */ -3,	/* '-' */ -3,	/* '.' */ -3,	/* '/' */ 63,
	/* '0' */ 52,	/* '1' */ 53,	/* '2' */ 54,	/* '3' */ 55,
	/* '4' */ 56,	/* '5' */ 57,	/* '6' */ 58,	/* '7' */ 59,
	/* '8' */ 60,	/* '9' */ 61,	/* ':' */ -3,	/* ';' */ -3,
	/* '<' */ -3,	/* '=' */ -1,	/* '>' */ -3,	/* '?' */ -3,
	/* '@' */ -3,	/* 'A' */ 0,	/* 'B' */  1,	/* 'C' */  2,
	/* 'D' */  3,	/* 'E' */  4,	/* 'F' */  5,	/* 'G' */  6,
	/* 'H' */  7,	/* 'I' */  8,	/* 'J' */  9,	/* 'K' */ 10,
	/* 'L' */ 11,	/* 'M' */ 12,	/* 'N' */ 13,	/* 'O' */ 14,
	/* 'P' */ 15,	/* 'Q' */ 16,	/* 'R' */ 17,	/* 'S' */ 18,
	/* 'T' */ 19,	/* 'U' */ 20,	/* 'V' */ 21,	/* 'W' */ 22,
	/* 'X' */ 23,	/* 'Y' */ 24,	/* 'Z' */ 25,	/* '[' */ -3,
	/* '\' */ -3,	/* ']' */ -3,	/* '^' */ -3,	/* '_' */ -3,
	/* '`' */ -3,	/* 'a' */ 26,	/* 'b' */ 27,	/* 'c' */ 28,
	/* 'd' */ 29,	/* 'e' */ 30,	/* 'f' */ 31,	/* 'g' */ 32,
	/* 'h' */ 33,	/* 'i' */ 34,	/* 'j' */ 35,	/* 'k' */ 36,
	/* 'l' */ 37,	/* 'm' */ 38,	/* 'n' */ 39,	/* 'o' */ 40,
	/* 'p' */ 41,	/* 'q' */ 42,	/* 'r' */ 43,	/* 's' */ 44,
	/* 't' */ 45,	/* 'u' */ 46,	/* 'v' */ 47,	/* 'w' */ 48,
	/* 'x' */ 49,	/* 'y' */ 50,	/* 'z' */ 51,	/* '{' */ -3,
	/* '|' */ -3,	/* '}' */ -3,	/* '~' */ -3,	/* 0x7f */ -3
};
 
const UInt8 kBits_00000011 = 0x03;
const UInt8 kBits_00001111 = 0x0F;
const UInt8 kBits_00110000 = 0x30;
const UInt8 kBits_00111100 = 0x3C;
const UInt8 kBits_00111111 = 0x3F;
const UInt8 kBits_11000000 = 0xC0;
const UInt8 kBits_11110000 = 0xF0;
const UInt8 kBits_11111100 = 0xFC;
 
size_t EstimateBas64EncodedDataSize(size_t inDataSize)
{
size_t theEncodedDataSize = (int)ceil(inDataSize / 3.0) * 4;
theEncodedDataSize = theEncodedDataSize / 72 * 74 + theEncodedDataSize % 72;
return(theEncodedDataSize);
}
 
size_t EstimateBas64DecodedDataSize(size_t inDataSize)
{
size_t theDecodedDataSize = (int)ceil(inDataSize / 4.0) * 3;
//theDecodedDataSize = theDecodedDataSize / 72 * 74 + theDecodedDataSize % 72;
return(theDecodedDataSize);
}
 
bool Base64EncodeData(const void *inInputData, size_t inInputDataSize, char *outOutputData, size_t *ioOutputDataSize, BOOL wrapped)
{
size_t theEncodedDataSize = EstimateBas64EncodedDataSize(inInputDataSize);
if (*ioOutputDataSize < theEncodedDataSize)
	return(false);
*ioOutputDataSize = theEncodedDataSize;
const UInt8 *theInPtr = (const UInt8 *)inInputData;
UInt32 theInIndex = 0, theOutIndex = 0;
for (; theInIndex < (inInputDataSize / 3) * 3; theInIndex += 3)
	{
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (theInPtr[theInIndex + 2] & kBits_11000000) >> 6];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 2] & kBits_00111111) >> 0];
	if (wrapped && (theOutIndex % 74 == 72))
		{
		outOutputData[theOutIndex++] = '\r';
		outOutputData[theOutIndex++] = '\n';
		}
	}
const size_t theRemainingBytes = inInputDataSize - theInIndex;
if (theRemainingBytes == 1)
	{
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (0 & kBits_11110000) >> 4];
	outOutputData[theOutIndex++] = '=';
	outOutputData[theOutIndex++] = '=';
	if (wrapped && (theOutIndex % 74 == 72))
		{
		outOutputData[theOutIndex++] = '\r';
		outOutputData[theOutIndex++] = '\n';
		}
	}
else if (theRemainingBytes == 2)
	{
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_11111100) >> 2];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex] & kBits_00000011) << 4 | (theInPtr[theInIndex + 1] & kBits_11110000) >> 4];
	outOutputData[theOutIndex++] = kBase64EncodeTable[(theInPtr[theInIndex + 1] & kBits_00001111) << 2 | (0 & kBits_11000000) >> 6];
	outOutputData[theOutIndex++] = '=';
	if (wrapped && (theOutIndex % 74 == 72))
		{
		outOutputData[theOutIndex++] = '\r';
		outOutputData[theOutIndex++] = '\n';
		}
	}
return(true);
}
 
bool Base64DecodeData(const void *inInputData, size_t inInputDataSize, void *ioOutputData, size_t *ioOutputDataSize)
{
memset(ioOutputData, '.', *ioOutputDataSize);
 
size_t theDecodedDataSize = EstimateBas64DecodedDataSize(inInputDataSize);
if (*ioOutputDataSize < theDecodedDataSize)
	return(false);
*ioOutputDataSize = 0;
const UInt8 *theInPtr = (const UInt8 *)inInputData;
UInt8 *theOutPtr = (UInt8 *)ioOutputData;
size_t theInIndex = 0, theOutIndex = 0;
UInt8 theOutputOctet;
size_t theSequence = 0;
for (; theInIndex < inInputDataSize; )
	{
	SInt8 theSextet = 0;
 
	SInt8 theCurrentInputOctet = theInPtr[theInIndex];
	theSextet = kBase64DecodeTable[theCurrentInputOctet];
	if (theSextet == -1)
		break;
	while (theSextet == -2)
		{
		theCurrentInputOctet = theInPtr[++theInIndex];
		theSextet = kBase64DecodeTable[theCurrentInputOctet];
		}
	while (theSextet == -3)
		{
		theCurrentInputOctet = theInPtr[++theInIndex];
		theSextet = kBase64DecodeTable[theCurrentInputOctet];
		}
	if (theSequence == 0)
		{
		theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 2 & kBits_11111100;
		}
	else if (theSequence == 1)
		{
		theOutputOctet |= (theSextet >- 0 ? theSextet : 0) >> 4 & kBits_00000011;
		theOutPtr[theOutIndex++] = theOutputOctet;
		}
	else if (theSequence == 2)
		{
		theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 4 & kBits_11110000;
		}
	else if (theSequence == 3)
		{
		theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 2 & kBits_00001111;
		theOutPtr[theOutIndex++] = theOutputOctet;
		}
	else if (theSequence == 4)
		{
		theOutputOctet = (theSextet >= 0 ? theSextet : 0) << 6 & kBits_11000000;
		}
	else if (theSequence == 5)
		{
		theOutputOctet |= (theSextet >= 0 ? theSextet : 0) >> 0 & kBits_00111111;
		theOutPtr[theOutIndex++] = theOutputOctet;
		}
	theSequence = (theSequence + 1) % 6;
	if (theSequence != 2 && theSequence != 4)
		theInIndex++;
	}
*ioOutputDataSize = theOutIndex;
return(true);
}

在开始学习iPhone开发的时候就捉摸 AppStore这样的程序时怎么实现的, 动态的从服务器抓取内容,再在表格中显示。 伴随着twitter的火爆, 越来越多的软件实现了此种方式来显示twitter消息, 不巧公司也要做twitter相关的东西,正好借此机会试探着实现一下这种显示功能。
iPhone程序和传统的桌面程序的最大不同在于内存有限, 管理内存成了iPhone开发中时时刻刻需要谨记的事情。类似的功能在桌面程序上无非是将down下来的数据缓存于内存中,需要的时候画出来即可。 此法在iPhone上切不可行,虽然UITableViewCell可与reuse重复使用以节约内存使用量, 但是数据还是需要host在array或者dictionary中,必然导致程序实用大量内存儿崩溃退出。
还好,iPhone系统内置sqlite微型数据库, 这么好的查询插入引擎不善用那就是罪过了。。。
言归正传, 基本思路是这样的: 从服务器读取内容,以twitter为例,先创建消息数据表
create table public_timelines (id integer primary key autoincrement, user varchar(40),\
userurl text,body text, created real, created_string text,\
imageurl text, ordernum int, userid varchar(20), user_screenname varchar(40));
获取public timelines得到以xml形式存在的message条目,解析xml后将每条消息插入数据表, 写入成功后发送reload消息给table以重新填充表格单元内容, 如图

如果消息记录超过一条, 记得在- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
中返回消息记录 + 1, 因为最后一个cell需要实现 Get More …功能
就像上一步说的, 点击最后一个cell也就是Get More…时,在此从服务器获取 [...]

阅读全文>>>

Google search 可以很容易实现站内搜索, 首先你需要到http://code.google.com/apis/ajaxsearch/signup.html 注册API Key。
将下面的代码存为html文件

?View Code HTML1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<script src="http://www.google.com/jsapi?key=ABQIAAAAoA_CzZ1j3fi975O5J0e28BTDgCurGPx7iDb5srKt0_zm3xn5GhSJK0sSDriiqfPAwr6wcPf7cpLPoQ" type="text/javascript"></script>
<script language="Javascript" type="text/javascript">
//<![CDATA[
 
google.load("search", "1");
 
function OnLoad() {
// Create a search control
var searchControl = new google.search.SearchControl();
 
[...]

阅读全文>>>

iPhone程序本地用需要用 ISO639-1的名称代码

阅读全文>>>

最近升级系统到vista, 用起来感觉还好, 唯一让人不爽的是以前写的程序在vista上运行会时不时发出“嘀嘀”的声音,非常恼人。 同时, 也发现不只是自己的程序, 很多其他得软件比如迅雷也会有同样的问题, 于是尝试着禁用掉所有得声音方案还是无果, 其实这个嘀嘀声是从pc speaker中发出的, 也就是主板自带的pc喇叭, 和声音方案是无关得。 最后发现,是有一个名叫beep的服务程序在作怪, 只需要停掉该服务程序即可。
这里要注意, 该服务在服务控制台是找不到的, 你得先打开cmd窗口,然后输入
sc stop beep
来停掉该service, 如果你想彻底禁用该服务,则需要在command窗口输入
sc config beep start=disabled
如此, 终于可以告别烦人得“嘀嘀”声了。

阅读全文>>>

Tags: , ,

如果你正在开发iPhone上的Facebook相关的应用软件,那么根据Facebook的相关使用协议,必须通过官方提供的api来进行访问, 否则会涉及倒版权问题。

Facebook的应用开发采用和google类似的Session Token的方式, 但比google 更复杂。 在用户登陆的过程中, Facebook强制用户交互操作已完成登陆,如果用户/密码验证成功,服务器会返回session key 和 对应的session secret, 右后的操作就只需要将改session key和session secret传给Facebook服务器即可, 无需提供用户名密码。

阅读全文>>>

Best Hosting Articles.

Email Marketing with Cyber Port.