UCenter 通信

UCENTER包含表:
| uc_admins |
| uc_applications |
| uc_badwords |
| uc_domains |
| uc_failedlogins |
| uc_feeds |
| uc_friends |
| uc_mailqueue |
| uc_memberfields |
| uc_members |
| uc_mergemembers |
| uc_newpm |
| uc_notelist |
| uc_pms |
| uc_protectedmembers |
| uc_settings |
| uc_sqlcache |
| uc_tags |
| uc_vars |
+———————+


下面我们一一来解释每一个表:
1:uc_admins // UCenter 管理员列表,可以为管理员分配权限
+——————-+———————–+
| Field | Type |
+——————-+———————–+
| uid | mediumint(8) unsigned |
| username | char(15) |
| allowadminsetting | tinyint(1) |
| allowadminapp | tinyint(1) |
| allowadminuser | tinyint(1) |
| allowadminbadword | tinyint(1) |
| allowadmintag | tinyint(1) |
| allowadminpm | tinyint(1) |
| allowadmincredits | tinyint(1) |
| allowadmindomain | tinyint(1) |
| allowadmindb | tinyint(1) |
| allowadminnote | tinyint(1) |
| allowadmincache | tinyint(1) |
| allowadminlog | tinyint(1) |
+——————-+———————–+
2:uc_applications //应用列表
+————–+———————-+
| Field | Type |
+————–+———————-+
| appid | smallint(6) unsigned |
| type | char(16) |
| name | char(20) |
| url | char(255) |
| authkey | char(255) |
| ip | char(15) |
| viewprourl | char(255) |
| apifilename | char(30) |
| charset | char(8) |
| dbcharset | char(8) |
| synlogin | tinyint(1) |
| recvnote | tinyint(1) |
| extra | mediumtext |
| tagtemplates | mediumtext |
+————–+———————-+
3:uc_badwords //词语过滤
+————-+———————-+
| Field | Type |
+————-+———————-+
| id | smallint(6) unsigned |
| admin | varchar(15) |
| find | varchar(255) |
| replacement | varchar(255) |
| findpattern | varchar(255) |
+————-+———————-+
4:uc_domains //域名解析
+——–+——————+
| Field | Type |
+——–+——————+
| id | int(10) unsigned |
| domain | char(40) |
| ip | char(15) |
+——–+——————+
5:uc_failedlogins //登录失败日志
+————+———————+
| Field | Type |
+————+———————+
| ip | char(15) |
| count | tinyint(1) unsigned |
| lastupdate | int(10) unsigned |
+————+———————+
6:uc_feeds
+—————-+———————–+
| Field | Type |
+—————-+———————–+
| feedid | mediumint(8) unsigned |
| appid | varchar(30) |
| icon | varchar(30) |
| uid | mediumint(8) unsigned |
| username | varchar(15) |
| dateline | int(10) unsigned |
| hash_template | varchar(32) |
| hash_data | varchar(32) |
| title_template | text |
| title_data | text |
| body_template | text |
| body_data | text |
| body_general | text |
| image_1 | varchar(255) |
| image_1_link | varchar(255) |
| image_2 | varchar(255) |
| image_2_link | varchar(255) |
| image_3 | varchar(255) |
| image_3_link | varchar(255) |
| image_4 | varchar(255) |
| image_4_link | varchar(255) |
| target_ids | varchar(255) |
+—————-+———————–+
7:uc_friends //好友
+———–+———————–+
| Field | Type |
+———–+———————–+
| uid | mediumint(8) unsigned |
| friendid | mediumint(8) unsigned |
| direction | tinyint(1) |
| version | int(10) unsigned |
| delstatus | tinyint(1) |
| comment | char(255) |
+———–+———————–+
8:uc_mailqueue //邮件队列
+———-+———————–+
| Field | Type |
+———-+———————–+
| mailid | int(10) unsigned |
| touid | mediumint(8) unsigned |
| tomail | varchar(32) |
| frommail | varchar(100) |
| subject | varchar(255) |
| message | text |
| charset | varchar(15) |
| htmlon | tinyint(1) |
| level | tinyint(1) |
| dateline | int(10) unsigned |
| failures | tinyint(3) unsigned |
| appid | smallint(6) unsigned |
+———-+———————–+
9:uc_memberfields //黑名单
+———–+———————–+
| Field | Type |
+———–+———————–+
| uid | mediumint(8) unsigned |
| blacklist | text |
+———–+———————–+
10:uc_members//用户列表
+—————+———————–+
| Field | Type |
+—————+———————–+
| uid | mediumint(8) unsigned |
| username | char(15) |
| password | char(32) |
| email | char(32) |
| myid | char(30) |
| myidkey | char(16) |
| regip | char(15) |
| regdate | int(10) unsigned |
| lastloginip | int(10) |
| lastlogintime | int(10) unsigned |
| salt | char(6) |
| secques | char(8) |
+—————+———————–+
11:uc_mergemembers//重名的用户名保存到该表中
+———-+———————-+
| Field | Type |
+———-+———————-+
| appid | smallint(6) unsigned |
| username | char(15) |
+———-+———————-+
12:uc_newpm
+——-+———————–+
| Field | Type |
+——-+———————–+
| uid | mediumint(8) unsigned |
+——-+———————–+
13:uc_notelist//积分对换,词语过滤,域名解析,应用管理,日志
+————+———————-+
| Field | Type |
+————+———————-+
| noteid | int(10) unsigned |
| operation | char(32) |
| closed | tinyint(4) |
| totalnum | smallint(6) unsigned |
| succeednum | smallint(6) unsigned |
| getdata | mediumtext |
| postdata | mediumtext |
| dateline | int(10) unsigned |
| pri | tinyint(3) |
+————+———————-+
14:uc_pms //UCHOME的短信息,公共消息
序号,发送消息[私信]的会员名(公共消息为空),发消息的会员ID(公共消息0),接受消息的会员ID,x(inbox),x,主题,是否标记灵删除,是否回复(?)
+———–+————————+
| Field | Type |
+———–+————————+
| pmid | int(10) unsigned |
| msgfrom | varchar(15) |
| msgfromid | mediumint(8) unsigned |
| msgtoid | mediumint(8) unsigned |
| folder | enum(‘inbox’,'outbox’) |
| new | tinyint(1) |
| subject | varchar(75) |
| dateline | int(10) unsigned |
| message | text |
| delstatus | tinyint(1) unsigned |
| related | int(10) unsigned |
| fromappid | smallint(6) unsigned |
+———–+————————+
15:uc_protectedmembers//受保护的用户
+———-+———————–+
| Field | Type |
+———-+———————–+
| uid | mediumint(8) unsigned |
| username | char(15) |
| appid | tinyint(1) unsigned |
| dateline | int(10) unsigned |
| admin | char(15) |
+———-+———————–+
16:uc_settings//基本设置
+——-+————-+
| Field | Type |
+——-+————-+
| k | varchar(32) |
| v | text |
+——-+————-+
17:uc_sqlcache
+——–+——————+
| Field | Type |
+——–+——————+
| sqlid | char(6) |
| data | char(100) |
| expiry | int(10) unsigned |
+——–+——————+
18:uc_tags
+————+———————-+
| Field | Type |
+————+———————-+
| tagname | char(20) |
| appid | smallint(6) unsigned |
| data | mediumtext |
| expiration | int(10) unsigned |
+————+———————-+
19:uc_vars
+——-+———–+
| Field | Type |
+——-+———–+
| name | char(32) |
| value | char(255) |
+——-+———–+


UCenter包括两个部分Server端与Client端。

Server端主要功能是提供服务,和管理应用。
Client端主要功能是与服务端通信,及把更新及时传递到Server,并在需要时从Server端取数据给自己用。


UCenter如何通讯?

用到的网络应用层协议基于Http1.1协议、p3p协议。
UCenter以Http1.1协议做为通信底层协议,同时以p3p协议实现JavaScript对Cookie的跨域调用。

对于Http1.1协议与P3P协议,不多做解释了,不是一两天就能理解的东西,大家自己看看吧。

UCenter的程序结构是什么样的?
UCenter分为Server端与Client端。

Client端相对比较简单,有api目录和uc_client目录。

    api目录保存是与Server通信相关的文件,也是直接与Server进行通讯的第一道关口,来自于服务器的Request直接被Dispatch到api/uc.php文件里。
   
    uc.php就是位于该目录下,uc.php也是这个目录里最主要的文件,主要负责对传来的code进行解码,而解码的唯一依据是UC_KEY.

    这也就解释了,为什么当Server与Client的UC_KEY不一致,会导致所有的接口调用都会失败(因为解码失败,所有从S传来的数据都乱了,没办法继续走下去)。

    uc.php文件里定义了uc_note类,用这个类实现了S端请求C端去进行一些操作比如test,deleteuser……等等,这类主要是S请求C 同步的操作。应用如果需要在请求到来之际,操作自己数据库或者Cookie,那么在这里定义这些操作,是最好的方式。

    uc_client目录里有4个子目录,control、data、lib、model。另外,最主要的文件是client.php文件,并判断安装的应 用是以“数据库”模式,或者是以“消息”模式来与UCenter通讯的。以此为依据,来调用相应的函数与UCenter的S端进行通讯。
   
    client.php文件里定义了很多的函数。如:uc_serialize,uc_unserialize,uc_authcode,uc_api_post……等等。这个函数基本都是类的成员函数。
client.php文件以include_once的形式,分别从4个子目录里引用需要的类定义。来实现以上这些函数。

   这些函数的主要实现的都是比较核心的功能。比如序列化、反序列化、加密、解密……等等。
总之,uc_client里面的文件主要实现的功能是与S端进行通讯。


Server端相对比较复杂,依然采用的是MVC结构。

S端程序对各种UCenter所管理的资源都提供了相应管理的界面。
并为与之相连接的每一个应用请求这些资源而做出了相应的接口,提供与应用的通讯。
C端,我已经不可能用几篇简单的贴子来描述完。S端更不可能啦。

我们从简单的例子来看一下,S端大概的结构,以及S端是如何与C端进行通讯的吧。
我们就从最简单的功能看起。

在S的后台,“应用管理”界面。会列表出所有已经注册过的应用。
同时会在这些列表的最后一列出现“通讯情况”。如果通讯成功,则返回绿色的“通讯成功”,不成功则返回红色的“通讯失败”。

这里,可以肯定的说,S与其所有注册过的应用,都发生了一次通讯。这里,就是我们的切入点。我们将从这里切进来,理清整个UCenter的通讯流程。
注: S与C的通讯,和C与S的通讯,是类似的。也就是说,只要理清了S到C的流程,C到S的也很容易看懂了。


那“应用管理”的界面在哪里?
以DisuczX为例。在uc_server\control\admin\app.php文件里。

这个是算是C层,这里定义了class control extends adminbase {……}类。
这个类的函数onadd,onls,onping……分别实现了添加新应用、应用列表、测试应用连接……功能。
我们要说的就是从这个onping函数开始。

那么M层在哪里呢?
在uc_server\model\app.php文件里。
定义了如:delete_apps($appids)之类的方法。

其实UCenter的MVC并没有完全的分开,不是很规范。如上面的C层里的onadd()应该是不会去直接操作数据库的。但是仍然直接访问了数据库,而且还在应用数据表里添加了一条应用记录。

这个在这里就不多说了。我们继续……

我们来跟进uc_server\control\admin\app.php里的onping()函数。

function onping() {
                $ip = getgpc('ip');
                $url = getgpc('url');
                $appid = intval(getgpc('appid'));
                $app = $_ENV['app']->get_app_by_appid($appid);
                $status = '';
                if($app['extra']['apppath'] && @include $app['extra']['apppath'].'./api/'.$app['apifilename']) {
                        $uc_note = new uc_note();
                        $status = $uc_note->test($note['getdata'], $note['postdata']);
                        //WriteToLog("ping.log",'\$uc_note='.$uc_note,'');
                } else {
                        $this->load('note');
                        $url = $_ENV['note']->get_url_code('test', '', $appid);
                        $status = $_ENV['app']->test_api($url, $ip);
                        //WriteToLog("ping.log",'URL='.$url,'');
                        file_put_contents("ping.log",strtotime("now").'  '.'URL='.$url."\r",FILE_APPEND);
                }
                if($status == '1' ) {
                        echo 'document.getElementById(\'status_'.$appid.'\').innerHTML = "<img src=\'images/correct.gif\' border=\'0\' class=\'statimg\' \/><span class=\'green\'>'.$this->lang['app_connent_ok'].'</span>";testlink();';
                        WriteToLog("ping.log",$appid.'  '.$this->lang['app_connent_ok'],'');
                } else {
                        echo 'document.getElementById(\'status_'.$appid.'\').innerHTML = "<img src=\'images/error.gif\' border=\'0\' class=\'statimg\' \/><span class=\'red\'>'.$this->lang['app_connent_false'].'</span>";testlink();';
                        WriteToLog("ping.log",$appid.'  '.$this->lang['app_connent_false'],'');
                }

        }

注意以上代码红色处,$status 的值是由函数 $_ENV['app']->test_api($url, $ip); 返回的。
这表示调用uc_server\model\app.php里的test_api函数。

我们来看一下test_api函数。

function test_api($url, $ip = '') {
  $this->base->load('misc');
  if(!$ip) {
   $ip = $_ENV['misc']->get_host_by_url($url);//在这里调用了misc模块的get_host_by_url($url)来获得正确的应用的IP地址以实现通讯。
  }
  if($ip < 0) {
   return FALSE;
  }
  
  file_put_contents("test_api.log",strtotime("now").'  '.'ip>=0 and url='.$url.'ip='.$ip."\r",FILE_APPEND);
  
  $myreturn=$_ENV['misc']->dfopen($url, 0, '', '', 1, $ip);//在这里调用了misc模块的dfopen()来向应用发送调用。

     file_put_contents("test_api.log",strtotime("now").'  '.'\$_ENV[\'misc\']->dfopen'.$myreturn."\r",FILE_APPEND);
  return $myreturn;
}

那么我们跟进\uc_client\model\'misc'模块的dfopen函数。

function dfopen($url, $limit = 0, $post = '', $cookie = '', $bysocket = FALSE , $ip = '', $timeout = 15, $block = TRUE, $encodetype  = 'URLENCODE') {
  //error_log("[uc_client]\r\nurl: $url\r\npost: $post\r\n\r\n", 3, 'c:/log/php_fopen.txt');
  $return = '';
  $matches = parse_url($url);
  $host = $matches['host'];
  $path = $matches['path'] ? $matches['path'].($matches['query'] ? '?'.$matches['query'] : '') : '/';
  $port = !empty($matches['port']) ? $matches['port'] : 80;
  if($post) {
   $out = "POST $path HTTP/1.0\r\n";
   $out .= "Accept: */*\r\n";
   //$out .= "Referer: $boardurl\r\n";
   $out .= "Accept-Language: zh-cn\r\n";
   $boundary = $encodetype == 'URLENCODE' ? '' : ';'.substr($post, 0, trim(strpos($post, "\n")));
   $out .= $encodetype == 'URLENCODE' ? "Content-Type: application/x-www-form-urlencoded\r\n" : "Content-Type: multipart/form-data$boundary\r\n";
   $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
   $out .= "Host: $host\r\n";
   $out .= 'Content-Length: '.strlen($post)."\r\n";
   $out .= "Connection: Close\r\n";
   $out .= "Cache-Control: no-cache\r\n";
   $out .= "Cookie: $cookie\r\n\r\n";
   $out .= $post;
  } else {
   $out = "GET $path HTTP/1.0\r\n";
   $out .= "Accept: */*\r\n";
   //$out .= "Referer: $boardurl\r\n";
   $out .= "Accept-Language: zh-cn\r\n";
   $out .= "User-Agent: $_SERVER[HTTP_USER_AGENT]\r\n";
   $out .= "Host: $host\r\n";
   $out .= "Connection: Close\r\n";
   $out .= "Cookie: $cookie\r\n\r\n";
  }
  $fp = @fsockopen(($ip ? $ip : $host), $port, $errno, $errstr, $timeout);
  if(!$fp) {
   return '';
  } else {
   stream_set_blocking($fp, $block);
   stream_set_timeout($fp, $timeout);
   @fwrite($fp, $out);
   $status = stream_get_meta_data($fp);
   if(!$status['timed_out']) {
    while (!feof($fp)) {
     if(($header = @fgets($fp)) && ($header == "\r\n" ||  $header == "\n")) {
      break;
     }
    }
    $stop = false;
    while(!feof($fp) && !$stop) {
     $data = fread($fp, ($limit == 0 || $limit > 8192 ? 8192 : $limit));
     $return .= $data;
     if($limit) {
      $limit -= strlen($data);
      $stop = $limit <= 0;
     }
    }
   }
   @fclose($fp);
   return $return;
  }
}

我们可以看到,dfopen其实在最直接的一个向应用端(S端)发送http1.1 Request的函数。所有的请求,都会由它先编码,然后发送出去。

我们截获由dfopen发送的字串,发现是这样的:
GET /test/discuzx/api/uc.php?code=04e27HZ%2FyCLXqy%2BfWDKM57uRzvFbIdA0Oky2sVXCrbdxH%2FOQc9xGGz0ZQklzbrFFycAQxwDzsDw HTTP/1.0
Accept: */*
Accept-Language: zh-cn
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; GTB6.5; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; 360SE)
Host: localhost:80
Connection: Close
Cookie:

也就是说,所有的请求,都被发送到了应用的 ./api/uc.php文件里。
S的请求,全部交由应用的uc.php来处理。
由此证明,服务端(S端)发送到应用端(C端)与的通信,第一个关口就是S端的uc.php文件。

那么那段uc.php?code=04e27HZ%2FyCLXqy%2BfWDKM57uRzvFbIdA0Oky2sVXCrbdxH%2FOQc9xGGz0ZQklzbrFFycAQxwDzsDw
中的code=.....到底包含了哪些数据,到底是什么东西呢?

让我们返回到: uc_server\control\admin\app.php里的onping()函数。

function onping() {
                $ip = getgpc('ip');
                $url = getgpc('url');
                $appid = intval(getgpc('appid'));
                $app = $_ENV['app']->get_app_by_appid($appid);
                $status = '';
                if($app['extra']['apppath'] && @include $app['extra']['apppath'].'./api/'.$app['apifilename']) {
                        $uc_note = new uc_note();
                        $status = $uc_note->test($note['getdata'], $note['postdata']);
                        //WriteToLog("ping.log",'\$uc_note='.$uc_note,'');
                } else {
                        $this->load('note');
                        $url = $_ENV['note']->get_url_code('test', '', $appid);
                        $status = $_ENV['app']->test_api($url, $ip);

)很明显,那段code就是$url,而这段$url来自于'note' 模型的 get_url_code 的函数。

我们跟进\uc_client\model\'note'模型的get_url_code函数。

function get_url_code($operation, $getdata, $appid) {
  $app = $this->apps[$appid];
  $authkey = UC_KEY;
  $url = $app['url'];
  $apifilename = isset($app['apifilename']) && $app['apifilename'] ? $app['apifilename'] : 'uc.php';
  $action = $this->operations[$operation][1];
$code = urlencode($this->base->authcode("$action&".($getdata ? "$getdata&" : '')."time=".$this->base->time, 'ENCODE', $authkey));
  return $url."/api/$apifilename?code=$code";
}

注意以上两段红色的代码,说明get_url_code函数。实际上是在用S与C约定好的UC_KEY,利用authcode函数,来实现对$action,time......等参数的组合加密。

这同样也说明了,为什么当S与C的UC_KEY不一至时,所有的S发送到C的请求,都会失败的原因。因为C没有办法对传过来的code正确的解密、解析。所以根本不知道,S端传过来的是什么。


S端向C端发送请求的流程到此已经结束。
下面我们来分析一下,C端是如何去处理S端发送过来的请求的。

'因为所有的S端的请求,是发往uc.php的。我们来分析一下uc.php文件。
uc.php文件分为几个主要段落。
第一是define段。用来定义UCenter版本号、发行号;哪些同步方法的是否打开,哪些关闭;文件主目录;

define('UC_CLIENT_VERSION', '1.5.1');
define('UC_CLIENT_RELEASE', '20100501');
define('API_DELETEUSER', 1);
define('API_RENAMEUSER', 1);
define('API_GETTAG', 1);
define('API_SYNLOGIN', 1);
define('API_SYNLOGOUT', 1);
define('API_UPDATEPW', 1);
define('API_UPDATEBADWORDS', 1);
define('API_UPDATEHOSTS', 1);
define('API_UPDATEAPPS', 1);
define('API_UPDATECLIENT', 1);
define('API_UPDATECREDIT', 1);
define('API_GETCREDIT', 1);
define('API_GETCREDITSETTINGS', 1);
define('API_UPDATECREDITSETTINGS', 1);
define('API_ADDFEED', 1);
define('API_RETURN_SUCCEED', '1');
define('API_RETURN_FAILED', '-1');
define('API_RETURN_FORBIDDEN', '1');
define('IN_DISCUZ', true);
define('IN_UC',true);
define('DISCUZ_ROOT', dirname(dirname(__FILE__)).'/');
define('CURSCRIPT', 'api');


这里的define一般不会出错,都会顺利执行下去,如果有问题,那么无非是定义赋值错误,或者遗漏了某些常量的定义。

接下来是require段。用来引入一些类、函数的定义文件。
require_once DISCUZ_ROOT.'./config/config_global.php';
require_once DISCUZ_ROOT.'./config/config_ucenter.php';
require_once DISCUZ_ROOT.'./source/function/function_core.php';
require_once DISCUZ_ROOT.'./source/class/class_core.php';
$discuz = & discuz_core::instance();
$discuz->init();
require DISCUZ_ROOT.'./config/config_ucenter.php';
require_once DISCUZ_ROOT.'./data/config.inc.php';

require段,要注意,虽然require一个不存在的文件,不会影响程序往下执行,但是:如果文件没有被正确引入,那么段内的红色的两行语句,会因为找不到对应的类文件而无法生成实例。这是很严重的错误,因为这会导致程序直接在此处停止。不同的应用,大部分是因为这里出错而导致C端停止解析S端的请求。

继续往下看。
$get = $post = array();//定义数组。
$code = @$_GET['code'];//得到S端传来的code=92fjd892fhidf2fop2fl22f

继续往下看。
//以下这句很重要,调用了uc_authcode,来解密code字串。同时使用应用端的UC_KEY做为解密的参数。因为传来的code字串,正是用UC_KEY来加密的。并将解密的结果(是一个数组),放到$get变量里。
parse_str(uc_authcode($code, 'DECODE', UC_KEY), $get);
//那么放入$get变量里的数组是什么形式的呢?
//我们已经捕获了。
//这里给大家看一下$get变量的大概内容包括哪些。如:
//action=synlogin&username=admin&uid=1&password=f03a9e498589d7b882786b5f70e49a75&time=1283314514
//action=test&time=1283314644
//现在理解了吧。至少包含action,time这两个数组元素。
//此处看看请求是否超时
if(time() - $get['time'] > 3600) {
exit('Authracation has expiried');
file_put_contents("uc.log",strtotime("now").'  '.'请求错误,已经超时'."\r",FILE_APPEND);
}
//此处看看是否解析code成功,如果解析code字串成功,那么empty($get)就不会为null。
if(empty($get)) {
exit('Invalid Request');
file_put_contents("uc.log",strtotime("now").'  '.'错误的请求'.$code."\r",FILE_APPEND);
}


继续往下看。
include_once DISCUZ_ROOT.'./uc_client/lib/xml.class.php';//引入XML序列化类准备对$post反序列化
file_put_contents("uc.log",strtotime("now").'  '.'开始反序列化......'.$code."\r",FILE_APPEND);
$post = xml_unserialize(file_get_contents('php://input'));//反序列化$post
file_put_contents("uc.log",strtotime("now").'  '.'反序列化成功!'.$code."\r",FILE_APPEND);
//以下判断一下,解析出来的$get['action']是否是uc.php里列出的几种函数名之后,如果不是直接抛出一个API_RETURN_FAILED给S端。
//如果是uc.php列出的函数之后,那么生成一个uc_note()实例,然后调用uc_note->$get['action']($get,$post);来把请求交给uc_note实例来处理。
if(in_array($get['action'], array('test', 'deleteuser', 'renameuser', 'gettag', 'synlogin', 'synlogout', 'updatepw', 'updatebadwords', 'updatehosts', 'updateapps', 'updateclient', 'updatecredit', 'getcredit', 'getcreditsettings', 'updatecreditsettings', 'addfeed'))) {
$uc_note = new uc_note();
echo $uc_note->$get['action']($get, $post);
exit();
} else {
exit(API_RETURN_FAILED);
}

OK,以上uc.php主要完成了对S端传来的code进行解析、检测的过程。并生成了一个uc_note类来处理这些请求。

继续往下,就是class uc_note()的定义了。相信有一点php基础的人都可以看懂了。这里就列出个大概了,想了解的,请自己去看uc.php。
S端发往C端,以及C端处理S端的流程。就介绍到这里。告破。

class uc_note {
var $dbconfig = '';
var $db = '';
var $tablepre = '';
var $appdir = '';
  
   function _serialize($arr, $htmlon = 0) {
     if(!function_exists('xml_serialize')) {
       include_once DISCUZ_ROOT.'./uc_client/lib/xml.class.php';
     }
     return xml_serialize($arr, $htmlon);
   }

   function uc_note() {
   }

   function test($get, $post) {
     return API_RETURN_SUCCEED;
   }

…………

猜你喜欢

转载自mr-zxing.iteye.com/blog/1254437