在GNOME环境中各种应用程序内部均采用了UTF-8的字符编码格式,这样实现了整个桌面环境的数据编码统一。GNOME的程序一般均默认接收到的字符串为UTF-8编码格式,不论是在输入还是输出的时候均按照UTF-8编码格式进行。
然而在开发中文操作系统的时候我们却发现我们需要和不同的操作系统进行数据交换,其他的操作系统也许并不是采用UTF-8的编码格式。比如在中文的windows环境中,简体中文的环境中有可能采用了GB2312、GBK、GB18030或者UTF-8作为编码格式,而繁体中文的环境则可能是BIG-5的编码格式。
GNOME环境中的GNOME VFS提供了一个虚拟的文件系统用于操作磁盘或者网络文件,其中负责进行samba操作的模块叫smb模块。我们可以在gnome-vfs源代码的modules子目录下找到名为smb-method.c的文件,这个文件即是处理gnome-vfs的samba请求模块。通过该模块,gnome vfs提供了访问samba共享目录的方式。但是由于访问的samba服务器采用的编码格式和本机编码不一致,从而会导致看到samba服务器上的文件为乱码,且无法访问的现象。
我们可以根据samba服务器采用的编码格式有针对性的进行编码转换工作,从而将samba服务器上的编码格式转换成为GNOME内部采用的UTF-8编码格式,这样可以保证文件显示正确,且能正确访问。
通过仔细分析smb-method.c的代码,我们可以知道,在掉了了samba函数打开服务器的连接后,smb-method.c并未对获得的文件名称数据进行编码专换,而是直接交给了gnome-vfs。因此我们需要在相应的地方增加用于编码转换的函数。
同样的,在GNOME-VFS需要访问samba的时候,传递过来的文件名为UTF-8的编码格式,这与samba服务器上的文件编码格式并不统一,这样会造成无法找寻到该文件。因此我们需要在访问samba的时候将UTF-8的编码转换成为服务器对应的编码格式。
分别在gnome-vfs的smb_method.c的do_*函数中针对文件名进行编码转换即可实现与samba的正确数据交换。
进行编码转换的时候需要调用到glib的函数g_convert。以下函数实现了从某一编码转换到另一编码的过程。
gchar * convert_string_from_to (const gchar * filename, const gchar * from,const gchar * to)
{
GError **error;
error = NULL;
gchar * conv=NULL;
gsize len;
len=strlen(filename);
conv = g_convert (filename, len, to, from, NULL, &len, error);
return conv ? conv : g_strdup(filename);
}
/***********************************************************************
* convert a filename from utf8 to server's locale encoding
* so we can show operation the file on server.
* server_file_encoding is a user's setting in gconf.
* it is a variable for server's locale encoding.
**********************************************************************/
gchar * vfs_convert_filename_from_utf8_to_locale (const gchar * filename)
{
if( server_file_encoding)
{
return convert_string_from_to (filename, "UTF-8", server_file_encoding);
}
return g_strdup (filename);
}
/***********************************************************************
* convert a filename from server's locale encoding to utf8
* so we can display correct file name to user.
* server_file_encoding is a user's setting in gconf.
* it is a variable for server's locale encoding.
**********************************************************************/
gchar * vfs_convert_filename_from_locale_to_utf8(const gchar * filename)
{
if( server_file_encoding )
{
return convert_string_from_to (filename, server_file_encoding, "UTF-8");
}
return g_strdup (filename);
}
根据以上原理,特针对gnome-vfs 2.22.0进行了开发,为gnome-vfs增加了一个gconf配置项
<schema>
<key>/schemas/system/smb/server_encoding</key>
<applyto>/system/smb/server_encoding</applyto>
<owner>gnome-vfs</owner>
<type>string</type>
<default></default>
<locale name="C">
<short>SMB Server Encoding</short>
<long>The Windows SMB Server filename encoding. This option effect beheave of
the smb module in GNOME-VFS that it how to decoding or encoding filename. </long>
</locale>
</schema>
在简体中文的环境中将/system/smb/server_encoding设置为GB18030即可以实现与简体中文windows进行正常的中文共享文件浏览访问了。
附件的补丁针对gnomevfs-2.22.0进行开发。

Coding for life.
描述:RAYS GNOME VFS SMB METHOD Support Server Encoding
附件:
rays_smb_support_server_encoding_setting.diff.txt
(9 K)
guest