Telepathy 即时通信框架

Telepathy 是一个灵活的、模块化的通信框架,通过可插拨的协议后端能实现实时通信。Telepathy 作为一个通信服务可同时被多个应用程序(客户端)访问。

这允许任何客户端访问 Presence 信息,请求一个 Channel (可由其它客户端处理)及基于 Tube 的客户端协作处理。

Telepathy 通过统一的 D-Bus API 提供了很多流行的协议后端支持,包括:Jabber/XMPP/Google Talk/Jingle, link-local XMPP, SIP, MSN, Yahoo/AIM and IRC。

另外,它还提供了方便的库接口使得使用 GLib, Qt4 以及 Python 可以简单的从应用程序访问这些 API。

Telepathy 为每个协议导出了有效的实时通信能力,如 Presence,联系人列表,文本聊天,音频、视频通信,文件传输及 Tubes。

Telepathy 是模块化的,每个后端和客户端都运行在一个独立的进程上,尽最大的保证安全和适应性。

Over!

HTTP 基本访问认证

在 HTTP 传输上下文中,基本访问认证是一种 Web 浏览器或其它客户端程序在请求中提供用户名和密码的方法。

在请求消息传输开始之前,密码被追加到用户名之后,以冒号间隔,再通过 Base64 算法编码。例如,用户名为 ‘Aladdin’ 和密码为 ‘open sesame’,得到字符串 ‘Aladdin:open sesame’ 再使用 Base64 编码,结果为 ‘QWxhZGRpbjpvcGVuIHNlc2FtZQ==’。经过 Base64 编码的字符串将被包含在 HTTP 请求消息头中传输给接收方,结果是冒号分隔的用户名和密码。

使用 Base64 算法加密用户名和密码为不可读状态,不能保证数据的安全性,仅仅可以保证传输数据是 HTTP 协议的兼容字符。

HTTP 基本访问认证规范于 1996 年定义在 RFC 1945 (Hypertext Transfer Protocol – HTTP/1.0)中。后续包含安全相关的规范在 RFC 2616 (Hypertext Transfer Protocol – HTTP/1.1) 和 RFC 2617 (HTTP Authentication: Basic and Digest Access Authentication)中被定义。

HTTP/1.1 协议同时支持 基本访问认证 和 数字访问认证。

示例
HTTP 客户端和 HTTP 服务器进行一次 基本访问认证 的典型步骤如下:

  • 客户端发起一个页面(需要认证的)请求时并无提供用户名和密码信息。(通常因为用户直接在地址栏中输入链接)
  • 服务器回应响应码为 401(”Unauthorized”)的消息,包含需要 scheme 和 realm。
  • 此刻,客户端会以提示消息的形式显示服务器发送过来的 realm,并要求用户输入用户名和密码并继续,也可取消停止。
  • 当客户端获得了用户输入的用户名和密码后,将 base64encode(username+”:”+password) 加入到之前的请求消息头中再次发送。
  • 在这个例子中,当服务端认证用户名和密码有效时,请求的页面将会返回;否则将返回响应码为 401 的页面,要求用户重要进行认证。

提示:客户端可在首次请求中携带认证信息,可直接跳过交互过程。

客户端请求(不包含认证信息)

GET /private/index.html HTTP/1.1
Host: localhost

服务器响应

HTTP/1.1 401 Authorization Required
Server: HTTPd/1.0
Date: Sat, 27 Nov 2004 10:18:15 GMT
WWW-Authenticate: Basic realm="Secure Area"
Content-Type: text/html
Content-Length: 311
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">
<HTML>
  <HEAD>
    <TITLE>Error</TITLE>
    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=ISO-8859-1">
  </HEAD>
  <BODY><H1>401 Unauthorized.</H1></BODY>
</HTML>

客户端请求(包含认证信息,用户名 “Aladdin”, 密码 “open sesame”)

GET /private/index.html HTTP/1.1
Host: localhost
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

服务器响应消息

HTTP/1.1 200 OK
Server: HTTPd/1.0
Date: Sat, 27 Nov 2004 10:19:07 GMT
Content-Type: text/html
Content-Length: 10476

引用
http://en.wikipedia.org/wiki/Basic_access_authentication

Over!

MySQL C 语言应用程序接口开发教程(2)

从数据库中取回数据
在这个实例中我们从表中取回数据。
步骤:

  • 创建连接
  • 执行查询
  • 获取结果集
  • 提取所有可用的记录
  • 释放结果集
#include <my_global.h>
#include <mysql.h>
 
int main(int argc, char * argv[])
{
	MYSQL * conn;
	MYSQL_RES * result;
	MYSQL_ROW row;
	int num_fields;
	int i;
 
	conn = mysql_init(NULL);
	mysql_real_connect(conn, "localhost", "username", "password", "testdb", 0, NULL, 0);
 
	mysql_query(conn, "SELECT * FROM writers");
	result = mysql_store_result(conn);
 
	num_fields = mysql_num_fields(result);
 
	while ((row = mysql_fetch_row(result)))
	{
		for (i=0; i<num_fields; i++)
		  printf("%s ", row[i] ? row[i] : "NULL");
		printf("\n");
	}
 
	mysql_free_result(result);
	mysql_close(conn);
}

实例程序打印 writers 表中所有的记录(姓名)。

./select
Leo Tolstoy
Jack London
Honore de Balzac
Lion Feuchtwanger
Emile Zola
mysql_query(conn, "SELECT * FROM writers");

执行查询将取回表 writers 中所有的记录。

result = mysql_store_result(conn);

取得结果集。

num_fields = mysql_num_fields(result);

获得表中的字段数量。

while ((row = mysql_fetch_row(result)))
{
	for (i=0; i<num_fields; i++)
	  printf("%s ", row[i] ? row[i] : "NULL");
	printf("\n");
}

获取记录并打印到屏幕。

mysql_free_result(result);

释放资源。

字段名称
这个实例里将要打印数据并显示字段名称。
为此我们创建一个新的表 friends。

mysql> CREATE TABLE friends (id int not null primary key auto_increment,
								name varchar(20), age int);
mysql> insert into friends(name, age) values('Tom', 25);
mysql> insert into friends(name, age) values('Elisabeth', 32);
mysql> insert into friends(name, age) values('Jane', 22);
mysql> insert into friends(name, age) values('Luke', 28);

插入一些数据到表中。

#include <my_global.h>
#include <mysql.h>
 
int main(int argc, char * argv[])
{
	MYSQL * conn;
	MYSQL_RES * result;
	MYSQL_ROW row;
	MYSQL_FIELD * field;
 
	int num_fields;
	int i;
 
	conn = mysql_init(NULL);
	mysql_real_connect(conn, "localhost", "username", "password", "testdb", 0, NULL, 0);
 
	mysql_query(conn, "SELECT * FROM friends");
	result = mysql_store_result(conn);
 
	num_fields = mysql_num_fields(result);
 
	while ((row = mysql_fetch_row(result)))
	{
		for(i=0; i<num_fields; i++)
		{
			if (i == 0) {
				while(field = mysql_fetch_field(result)) {
					printf("%s ", field->name);
				}
				printf("\n");
			}
			printf("%s ", row[i] ? row[i] : "NULL");
		}
	}
	printf("\n");
 
	mysql_free_result(result);
	mysql_close(conn);
 
	return 0;
}

这个实例和之前有一点差别,仅仅增加了字段名称。

while(field = mysql_fetch_field(result)) {
	printf("%s ", field->name);
}

mysql_fetch_field() 返回一个 MYSQL_FIELD 结构。我们从这个结构中得到名称(name)。

./header
id name age
1  Tom  25
2  Elisabeth  32
3  Jane  22
4  Luke  28

这是程序输出结果。

插件图片到 MySQL 数据库
一些用户喜欢将图片存入数据库,还有一些用户喜欢将图片存入本地文件系统。图片是二进制数据,MySQL 有专用的数据类型 BLOB(Binary Large Object) 以存储二进制数据。

mysql> describe images;
+-------+------------+------+-----+---------+-------+
| Field | Type       | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| id    | int(11)    | NO   | PRI |         |       |
| data  | mediumblob | YES  |     | NULL    |       |
+-------+------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

这个表将在我们的实例中使用,通过下面的 SQL 语句可以创建它。

CREATE TABLE images(id int not null primary key, data mediumblob);
#include <my_global.h>
#include <mysql.h>
 
int main(int argc, char * argv[])
{
	MYSQL * conn;
 
	int len, size;
	char data[1000*1024];
	char chunk[2*1000*1024+1];
	char query[1024*5000];
 
	FILE * fp;
 
	conn = mysql_init(NULL);
	mysql_real_connect(conn, "localhost", "username", "password", "testdb", 0, NULL, 0);
 
	fp = fopen("image.png", "rb");
	size = fread(data, 1, 1024*1000, fp);
 
	mysql_real_escape_string(conn, chunk, data, size);
 
	char *stat = "INSERT INTO images(id, data) VALUES('1', '%s')";
	len = snprintf(query, sizeof(stat)+sizeof(chunk), stat, chunk);
 
	mysql_real_query(conn, query, len);
 
	fclose(fp);
 
	mysql_close(conn);
 
	return 0;
}

在这个实例中,我们插入一张图片到表 images 中,图片最大可以是 1MB。

fp = fopen("images.png", "rb");
size = fread(data, 1, 1024*1000, fp);

这里打开图片并读入数据集。

mysql_real_escape_string(conn, chunk, data, size);

二进制数据可以包含特殊字符,为了在 SQL 语句中不造成麻烦。我们必需避开它们。 mysql_real_escape_string() 函数将编码后的数据放入集合 chunk。这样,它们就可以是合法的语句了。这个函数还会在结尾增加一个 NULL 字符,这也是为什么集合 chunk 是集合 data两倍多一个字节。

char * stat = "INSERT INTO images(id, data) VALUES('1', '%s')";
len = snpritnf(query, sizeof(stat)+sizeof(chunk), stat, chunk);

这两行代码准备查询语句。

mysql_real_query(conn, query, len);

最后,我们执行语句。

从 MySQL 数据库中有选择的取出图片
在上一个实例中,我们在数据库中插入了图片。在本实例中,我们将有选择的取出这些插入的图片。

#include <my_global.h>
#include <mysql.h>
 
int main(int argc, char * argv[])
{
	MYSQL * conn;
	MYSQL_RES * result;
	MYSQL_ROW row;
 
	unsigned long * lengths;
	FILE * fp;
 
	conn = msyql_init(NULL);
	mysql_real_connect(conn, "localhost", "username", "password", "testdb", 0, NULL, 0);
 
	fp = fopen("image.png", "wb");
 
	mysql_query(conn, "SELECT data FROM images WHERE id=1");
	result = mysql_store_result(conn);
 
	row = mysql_fetch_row(result);
	lengths = mysql_fetch_lengths(result);
 
	fwrite(row[0], lengths[0], 1, fp);
	mysql_free_result(result);
 
	fclose(fp);
	mysql_close(conn);
 
	return 0;
}

这个实例中我们将数据库中 ID 为 1 的图片创建为文件 image.png

fp = fopen("image.png", "wb");

以可写的方式打开一个文件。

mysql_query(conn, "SELECT data FROM images WHERE id=1");

选择 ID 为 1 的图片。

row = mysql_fetch_row(result);

row 包含了原始数据。

lengths = mysql_fetch_lengths(result);

获取图片长度。

fwrite(row[0], lengths[0], 1, fp);

使用标准函数 fwrite() 将数据写入文件。

Over!

MySQL C 语言应用程序接口开发教程(1)

关于教程
这是一篇 MySQL 数据库的 C 语言开发教程。它讲述了用 C 语言开发 MySQL 应用程序的基本过程。

关于 MySQL 数据库
MySQL 是一个重要的开放源代码的、多用户的、多线程的数据库管理系统。MySQL 在 Web 应用中很流行。它是非常流行的 LAMP(Linux, Apache, MySQL, PHP) 架构的一部分。MySQL 被瑞典一家名为 MySQL AB 并对开源事业有杰出贡献的公司所有。MySQL 数据库可以运行在很多的操作系统上,如 BSD, Unix, Linux Windows 和 Mac。维基百科和 Youtube 都在使用 MySQL。这些站点一天有数百万将的查询。MySQL 有两个版本,分别是 MySQL 服务器系统和 MySQL 嵌入式系统。

第一个实例
我们第一个实例将要测试调用一个 MySQL 函数。

#include <my_global.h>
#include <mysql.h>
 
int main(int argc, char * argv[])
{
	printf("MySQL client version: %s\n", mysql_get_client_info());
	return 0;
}

函数 mysql_get_client_info()返回 MySQL 客户端版本信息。

gcc version.c -o version `mysql_config --cflags --libs`
./version

这是是如何编译和运行这个实例。

MySQL client version: 5.0.38
#include <my_global.h>
#include <mysql.h>

我们包含两个需要的头文件: mysql.h MySQL 函数调用的最重要的头文件。my_global.h 包含了一些全局的声明和标准输入/输出头文件。

printf("MySQL client version: %s\n", mysql_get_client_info());

这行代码输入了 MySQL 客户端的版本信息。我们调用了 mysql_get_client_info()函数。

创建一个数据库
在第二个实例中创建一个数据库。

#include <my_global.h>
#include <mysql.h>
 
int main(int argc, char * argv[])
{
	MYSQL * conn;
 
	conn = mysql_init(NULL);
 
	if (conn == NULL) {
		printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
		exit(1);
	}
 
	if (mysql_real_connect(conn, "localhost", "username", "password", NULL, 0, NULL, 0) == NULL) {
		printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
		exit(1);
	}
 
	if (mysql_query(conn, "CREATE DATABASE testdb")) {
		printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
		exit(1);
	}
 
	mysql_close(conn);
 
	return 0;
}

这段代码连接了 MySQL 数据库系统并创建了一个名为 testdb 的数据库。

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| testdb             |
+--------------------+
3 rows in set (0.00 sec)

检验的确创建了一个新的库。

在这段实例中我们包含了错误检测,检查可能出现的错误是非常重要的。在数据库开发领域里,很多地方都可能出错。为了有清晰的代码之后的实例中将不包含错误检查,我们假设所有人清楚错误检测是开发人员的责任

实例分为如下的部分:

  • 初始化一个连接对象结构
  • 创建一个连接
  • 执行一个查询
  • 关闭连接
MYSQL * conn;

我们声明一个 MYSQL 结构指针,这个结构是连接对象。

conn = mysql_init(NULL);

mysql_init() 函数返回一个连接对象。

if (conn == NULL) {
	printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
	exit(1);
}

我们检查返回值,如果 mysql_init() 调用失败打印错误消息并中止应用程序。

if (mysql_real_connect(conn, "localhost", "username", "password", NULL, 0, NULL, 0) == NULL) {
	printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
	exit(1);
}

mysql_real_connect() 函数建立了一个到数据库的连接。我们提供连接对象、主机名、用户名和密码参数。其它四个参数分别是数据库名、端口、Unix 套接字和客户端标记。

if (mysql_query(conn, "CREATE DATABASE testdb")) {
	printf("Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
	exit(1);
}

mysql_query() 执行一个 SQL 语句。这里创建一个新的库。

mysql_close(conn);

最后,我们关闭数据库连接。

创建和操作表
第三个实例将要创建一个表并插入一些数据。

#include <my_global.h>
#include <mysql.h>
 
int main(int argc, char * argv[])
{
	MYSQL * conn;
 
	conn = mysql_init(NULL);
	mysql_real_connect(conn, "localhsot", "username", "password", "testdb", 0, NULL, 0);
 
	mysql_query(conn, "CREATE TABLE writers(name VARCHAR(25))");
 
	mysql_query(conn, "INSERT INTO writers VALUES('Leo Tolstoy')");
	mysql_query(conn, "INSERT INTO writers VALUES('Jack London')");
	mysql_query(conn, "INSERT INTO writers VALUES('Honore de Balzac')");
	mysql_query(conn, "INSERT INTO writers VALUES('Lion Feuchtwanger')");
	mysql_query(conn, "INSERT INTO writers VALUES('Emile Zole')");
 
	mysql_close(conn);
 
	return 0;
}

我们不使用任何新的 MySQL 函数。使用 mysql_query() 函数去创建表和插入数据。

mysql_real_connect(conn, "localhost", "username", "password", "testdb", 0, NULL, 0);

我们连接数据库 testdb,用户名 username 密码 password。

mysql_query(conn, "CREATE TABLE writers(name VARCHAR(25))");

这里我们创建一个名为 writers 的表,它有一个 varchar 类型的字段。

mysql_query(conn, "INSERT INTO writers VALUES('Leo Tolstoy')");

我们在 writers 表里插入一个记录。

mysql> show tables;
+------------------+
| Tables_in_testdb |
+------------------+
| writers          |
+------------------+
1 row in set (0.00 sec)

显示数据库里的表。

mysql> select * from writers;
+-------------------+
| name              |
+-------------------+
| Leo Tolstoy       |
| Jack London       |
| Honore de Balzac  |
| Lion Feuchtwanger |
| Emile Zola        |
+-------------------+
5 rows in set (0.00 sec)

枚举表中的记录。

Over!

怎样为 Android 系统创建新的输入法

一.
1.创建一个新的输入法需要继承android.inputmethodservice.InputMethodService,这个类提供了一个输入法的基本实现,例子可以参考sdk中的SoftKeyboard的代码。

2.输入法跟其他application或service一样会被打包成一个apk,在AndroidManifest.xml,把它声明成一个 Service.
Continue reading 怎样为 Android 系统创建新的输入法

GObject 参考手册:教程:如何创建和使用信号

Simple use of signals

The most basic use of signals is to implement simple event notification: for example, if we have a MamanFile object, and if this object has a write method, we might wish to be notified whenever someone uses this method. The code below shows how the user can connect a callback to the write signal. Full code for this simple example is located in sample/signal/maman-file.{h|c} and in sample/signal/test.c
Continue reading GObject 参考手册:教程:如何创建和使用信号

GObject 参考手册:教程:如何定义和实现接口

How to define interfaces

The bulk of interface definition has already been shown in the section called “Non-instantiable classed types: interfaces” but I feel it is needed to show exactly how to create an interface. The sample source code associated to this section can be found in the documentation’s source tarball, in the sample/interface/maman-ibaz.{h|c} file.
Continue reading GObject 参考手册:教程:如何定义和实现接口

GObject 参考手册:教程:如何定义和实现在一个新 GObject

Clearly, this is one of the most common questions people ask: they just want to crank code and implement a subclass of a GObject. Sometimes because they want to create their own class hierarchy, sometimes because they want to subclass one of GTK+’s widget. This chapter will focus on the implementation of a subtype of GObject. The sample source code associated with this section can be found in the documentation’s source tarball, in the sample/gobject directory:
Continue reading GObject 参考手册:教程:如何定义和实现在一个新 GObject

GObject 参考手册:概念:GObject 消息系统:信号

GObject’s signals have nothing to do with standard UNIX signals: they connect arbitrary application-specific events with any number of listeners. For example, in GTK+, every user event (keystroke or mouse move) is received from the X server and generates a GTK+ event under the form of a signal emission on a given object instance.
Continue reading GObject 参考手册:概念:GObject 消息系统:信号

GObject 参考手册:概念:GObject 消息系统

Closures are central to the concept of asynchronous signal delivery which is widely used throughout GTK+ and GNOME applications. A closure is an abstraction, a generic representation of a callback. It is a small structure which contains three objects:
Continue reading GObject 参考手册:概念:GObject 消息系统