• 设为首页
  • 点击收藏
  • 手机APP
    手机扫一扫下载
    华域联盟APP
  • 关注官方公众号
    微信扫一扫关注
    华域联盟公众号
hot天融信关于ThinkPHP5.1框架分离RCE漏洞的深

[/backcolor] 0x00 前言在前几个月,Thinkphp连续迸发了多个严重漏洞。由于框架应用的普遍性,漏洞影响十分 详情

如何用PHP把RDF内容插入Web站点之中(二)

[复制链接]
sterben 发表于 2016-5-10 18:03:53 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
既然从技术上讲,RSS是结构良好的XML文档,所以可以用标准的XML编程技术来处理它。主要有两种技术:SAX(the Simple API for XML)和DOM(the Document Object Model)。' A- T; Y- W; E/ ?  Q" P

1 ?" g2 C! p) @- _' P" I9 G3 ESAX分析器工作时遍历整个XML文档,在遇到不用类型的标记时调用特定的函数。比如,调用特定函数处理一个开始标记,调用另一个函数处理一个结束标记,再调用一个函数处理两者之间的数据。分析器的职责仅仅是顺序遍历这个文档。而它所调用的函数负责处理发现的标记。一旦一个标记被处理完毕,分析器继续分析文档中的下一个元素,这一过程不断重复。1 g, ]) s6 P) I: h% y$ M, T

9 R  J& R4 k4 z. T' X/ h另一方面,DOM分析器工作是把整个XML文档读进内存当中,并将之转换成一种分层的树型结构。而且为访问不同的树结点(以及结点所附的内容)提供了API。递归处理方式加上API函数使得开发者能够区分不同类型的结点(元素,属性,字符数据,注释等),同时根据文档树的结点类型和结点深度,使得执行不同的动作成为可能。
2 s/ P" A# W6 c, n" }6 }* F& \) X. C
SAX和DOM分析器几乎支持每一种语言,包括你我的最爱——PHP。我将在这篇文章中利用PHP的SAX分析器处理RDF的例子。 当然,使用DOM分析器也同样很容易。! h7 ~+ g( u& k2 u! Z$ t

  L2 e1 v* v9 w- k4 ]- x% G2 r让我们看这个简单的例子,把它记在脑海里。下面是一个我将要使用的RDF文件,这个文件直接选自http://www.freshmeat.net/" n( b  ~0 w( b% I+ r7 _1 ^3 o
# A5 p6 e( x* H/ a. X7 a7 `- \
<?xml version="1.0" encoding="ISO-8859-1"?>
( \8 d& F. I' _) S) y- a8 ^$ k<rdf:RDF  xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
! V; n" N% r0 S- }6 Gxmlns="http://purl.org/rss/1.0/"+ G3 Y& i8 m* i5 h) m
xmlns:dc="http://purl.org/dc/elements/1.1/"2 d# u* `0 a, P# w. U/ ^- B5 ?
>, Z( X# d$ j3 r
<channel rdf:about="http://freshmeat.net/">! z$ f! P3 g3 Q( c* f# H
   <title>freshmeat.net</title>1 c) M3 m" n- B" M) W& E1 I; G
   <link>http://freshmeat.net/</link>9 L# u3 F! `3 D/ l
   <description>freshmeat.net maintains the Web's largest index of Unix
! a: ^7 G" r/ e) Land cross-platform open source software. Thousands of applications are6 t7 A( {! s+ @2 ?8 ~5 ?/ a
meticulously cataloged in the freshmeat.net database, and links to new
: q8 {9 y' I- Y+ Jcode are added daily.</description>
- W- R2 W, S4 u) r- C   <dc:language>en-us</dc:language>
2 z3 @% g, r7 z0 `# S! U   <dc:subject>Technology</dc:subject>3 g- L! v$ D( g9 a% j2 @$ C
   <dc:publisher>freshmeat.net</dc:publisher>. f0 i# g  h" a8 i5 Y
   <dc:creator>freshmeat.net contributors</dc:creator>2 @, K3 b, D0 j* h
   <dc:rights>Copyright (c) 1997-2002 OSDN</dc:rights>) n2 P9 Y& g2 ~- v9 z
   <dc:date>2002-02-11T10:20+00:00</dc:date>
! Z( q- Y6 S2 s5 z" X: t7 y   <items>; b0 |6 c9 X2 t( O
     <rdf:Seq>
8 ~5 k- V* F9 Z: W! D5 b* ]- |       <rdf:li rdf:resource="http://freshmeat.net/releases/69583/" />7 I5 x! E  D2 A" E" w/ t3 I" ?$ K
       <rdf:li rdf:resource="http://freshmeat.net/releases/69581/" />6 R1 ?8 k; w5 b& M
4 {6 i3 c' M* f; J2 F
     <!-- and so on -->+ k! ?, h- k/ Z6 U  t) X

9 K$ |5 X" R; V9 }1 ?     </rdf:Seq>6 ]6 j! R" c, ^' T% e) c& m: P: j
   </items>% M7 N: L$ G, F; G( Y# c
   <image rdf:resource="http://freshmeat.net/img/fmII-button.gif" />' |5 M, ]$ H( l) p4 C
   <textinput rdf:resource="http://freshmeat.net/search/" />
( s' ~" t, b7 | </channel>
9 O8 m  k0 ~# O) B! }- q2 }, t$ {  L; \3 f( ^. E2 ^
<image rdf:about="http://freshmeat.net/img/fmII-button.gif">9 `) v% Z5 ~0 L5 A6 w# q+ q
   <title>freshmeat.net</title>
* Y: R& o( H; z& J; f. N   <url>
php?mod=logging&action=login'+'&referer='+encodeURIComponent(location))" src="http://freshmeat.net/img/fmII-button.gif" border="0" alt="" />
$ T8 v# v' J3 {8 P7 v" k                               
php?mod=logging&action=login" onclick="showWindow('login', this.href+'&referer='+encodeURIComponent(location));">登录/注册后可看大图
</url>2 [( {' n4 m' W, d
   <link>http://freshmeat.net/</link>
. ^: u" ^% M- H </image>
4 W" Q" j. w9 J. @. ?* P
: P( v' A- L- [8 [7 ^! D. @8 R/ t <item rdf:about="http://freshmeat.net/releases/69583/">
* U* y1 ~- B4 Q( i   <title>sloop.splitter 0.2.1</title>0 Z' _8 z/ z) B& L  }
   <link>http://freshmeat.net/releases/69583/</link>5 {8 C/ M/ \) E+ B; E2 k* M3 M
   <description>A real time sound effects program.</description>3 E1 N' k. D1 U/ O# n
   <dc:date>2002-02-11T04:52-06:00</dc:date>
0 }1 o: j- x5 a: B* y" B. [ </item>( R" J/ w( Z: O6 O4 N# O- D+ ?4 ?

/ ~" J' X6 b2 b <item rdf:about="http://freshmeat.net/releases/69581/">
2 F+ V4 h! s! T5 G( T& a  Y9 {   <title>apacompile 1.9.9</title>, \8 i: h; b% a, k8 D- S( Z
   <link>http://freshmeat.net/releases/69581/</link>
" E/ Y: c* S; D9 K   <description>A full-featured Apache compilation HOWTO.</description>
1 Y3 x& B* ~% b; g) n5 s' E   <dc:date>2002-02-11T04:52-06:00</dc:date>8 n* l) V- ^! {8 d. @3 a, @6 U( l
</item>
1 K( d" x, e! r6 P" O/ D& Z  S" z: J6 t' t4 c1 M! }
<!-- and so on -->: M! v+ L( t5 Z8 z/ v" S; \
" _, |! O* K$ F# T1 \6 f1 q
</rdf:RDF>0 e8 l7 q. F' B4 S1 b# K6 @

5 v) g0 W% s/ F. n6 ~3 s, X下面是分析这一文档并显示其中数据的PHP脚本( U) ?5 t& G: ]% }& g% M

- _" l7 S# j) m/ m/ ?% y <?php% i8 p0 V: a; F0 O  [6 d/ V
// XML file
3 p1 f$ w/ M" k; v& ~% z' p( W$file = "fm-releases.rdf";
- Z) K7 J' O# I* I% n# v# T
/ k: D0 M  s  w0 I) F* w// set up some variables for use by the parser) N6 T( z# }% y1 m1 C) a
$currentTag = "";
9 R, _. ]8 f& n1 B9 p* f$flag = "";# l3 ?& Y4 `; n/ v2 R8 I" h$ Y, ^

4 D& y  ~2 R5 Q! w, W8 g% q' e// create parser
& x- \; G/ e1 X1 Z$xp = xml_parser_create();9 {9 t$ O/ c& W; @8 l$ f0 a
' M- B7 Q4 f* T" H6 _+ x, T
// set element handler
  R% b. u/ |3 a6 o2 Zxml_set_element_handler($xp, "elementBegin", "elementEnd");" S8 F! P3 e. H0 s
xml_set_character_data_handler($xp, "characterData");# }- S2 N- |; ]9 z, c# x  A) _
xml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, TRUE);
. c! v- ?  h7 f* ]' o# y, |. T9 k: I* L5 X2 b& d/ h
// read XML file5 o( G, K* E8 G6 ~$ A
if (!($fp = fopen($file, "r"))) ) ~* C  }& ?/ X& j( n7 z! c7 p
{3 y; q8 P" @- D8 A- y% Z0 t* P& Z* Z
     die("Could not read $file");
0 L! [8 ~- }- K}
, |/ p* D( O& ?) E3 z
5 _! J( Y+ M" P. m9 k; Q; C8 h// parse data
4 F3 ^# H% S- t6 x/ J2 ?while ($xml = fread($fp, 4096))
6 s' T& f& M. Z, b" |{) x' k& w  Q+ P. Q4 `6 I
   if (!xml_parse($xp, $xml, feof($fp)))
, b4 y& `, A( K' [   {5 p: Q+ s1 |- }4 t% I
\t   die("XML parser error: " .7 N, D5 x3 G  D" X0 t
xml_error_string(xml_get_error_code($xp)));5 P  b+ D; Q5 |: E* W1 s1 H3 @+ w
   }
; @7 E! N4 g# y  l; j3 J}
7 C5 k; k- ?8 O! F2 \, E* S* Z2 |) W; O6 W; f* J0 k/ L
// destroy parser
# \5 C; Z9 N* B2 K# ]& ]+ z) Axml_parser_free($xp);' c" T4 u( o: M7 x8 r4 S. A& g
$ A$ n! D( J4 c8 w3 G
// opening tag handler
' x6 d/ @' ^# H0 M4 f/ g& Nfunction elementBegin($parser, $name, $attributes)
# l9 U! ~$ G) W{2 [/ L0 Z* a( X% F
global $currentTag, $flag;
3 p: U! b! G8 V- `8 a // export the name of the current tag to the global scope
6 b4 ?! g% h. W, T1 z; u" R $currentTag = $name;$ P, ^$ B( T! m% S. S: K
// if within an item block, set a flag" k& X' i' `  E, h
if ($name == "ITEM")
+ @; R% O) f1 }- e& A {
; V5 W. _. J+ R0 T/ g4 D\t   $flag = 1;+ v( r1 s0 ^5 r9 q( E
}. ~9 V4 Z% E" u. H5 M( P
}
5 J: P4 @9 l/ [% Y: V
- ]. G8 [2 K2 o" h// closing tag handler      
# n2 p7 q: [& v) R& Y5 g& Kfunction elementEnd($parser, $name)
+ k# v- I8 \& k/ j+ s{
8 `- X4 g. L# G% i* |6 p global $currentTag, $flag;
7 D8 ~4 c% \/ l0 x- S $currentTag = "";
5 [- Z& h  p- u // if exiting an item block, print a line and reset the flag
3 |# R2 r9 m7 B5 O+ `" q if ($name == "ITEM")
$ |! |2 n1 a! Y( x7 w3 y7 o) R {+ y  i, W8 G% u2 |, ^6 v4 J, t
\t   echo "<hr>";
: P' ]1 I2 N% _8 Q\t   $flag = 0;
! m' P7 r7 O; a! Z9 f }3 U; o: ?7 ?, U# h9 ], K) }
}# n, k5 W5 i" k, R
. u4 L# }! o' t( k1 }
// character data handler, }* L# |0 W4 |% X+ F0 U! W
function characterData($parser, $data)
, Z1 y: Z* K2 J  `+ F& f" T{
0 D6 P9 v7 J0 C4 ^2 C global $currentTag, $flag;2 K6 {: |1 _/ f. L& [  u
// if within an item block, print item data
7 x% c6 y6 H& {' D' r0 } if (($currentTag == "TITLE" || $currentTag == "LINK" ||9 l  s# K) D8 P$ V1 t9 T8 o2 ?
$currentTag ==
% ~; a) d) s: u5 u8 h* C"DESCRIPTION") && $flag == 1)
8 |! V/ q( {2 d# ]+ x {
8 ?# z4 m) d7 o2 O4 x; B\t   echo "$currentTag: $data <br>";
( Z0 c% b& g- \$ b4 z  j }; K+ j, T( a" \/ T* W+ x
}' t" ~( X& R2 G1 o, Y- @, p
  i; V8 c9 ~6 x7 X
?>
( ]7 O( g2 {& d" k) h: M4 x! X: [5 P4 S$ t; S+ s; g
看不明白? 别着急,后面将会作出解释。
9 z" z6 w/ V5 w8 B& w- E4 t* |' p8 O+ m0 p
捕获旗标, D  D" [) I' d

5 @1 O7 A( W' a' Y$ E. A' h$ _这段脚本首先要做的是设定一些全局变量:8 F4 Q$ P- s; U2 S5 y% O& V0 n
  U+ z1 R' v& N* M
// XML file
: k' d  C5 ~) S8 o( G2 b4 F2 M2 s8 V$file = "fm-releases.rdf";
( N7 O0 h8 K; n
$ `( f. S( [' J! L// set up some variables for use by the parser
6 P2 L! f/ T- N2 R7 L$currentTag = "";8 Y0 k# Z* f1 D9 Q# j' [& s3 b" H
$flag = "";
9 `) L- s: I6 V) w# A# B4 Y+ _  n3 R7 I6 r' B
$currentTag变量保存是分析器当前处理的元素的名称——你很快就会看到为什么需要它。3 {3 b2 J. \" M, s, i

& y0 q4 }; o* B  `; N1 ^因为我的最终目的是显示频道中的每一个单独的条目(item),并且带有链结。另外还要知道分析器什么时候退出了<channel></channel>区块,什么时候又进入了文档的 <item></item>部分。再说我用的是SAX分析器,它按顺序方式工作,没有任何分析器API可供使用,无法知道文档树中的深度和位置。所以,我不得不自己发明一个机制来做这件事——这就是引入$flag变量的原因。
% A0 i/ V# ~$ t- P
$ [! U' y/ J& L% E; v6 z  [  d$flag变量将用于判断分析器是在<channel>区块还是在<item>区块里面。3 k* S, B) o: L9 ~: o
& z! y, m" x; w1 s* h" l: |/ @" G
下一步要做的是初始化SAX分析器,并开始分析RSS文档。
. K' Z* z7 P+ D4 N1 H6 q' Q* {0 l0 k) C* o
// create parser" q" Y8 Q- V8 I2 H
$xp = xml_parser_create();
3 t( g/ l# W/ w8 ^& b8 e
2 I# V8 v! O' \& |: s// set element handler
2 h9 c5 y$ f% }; m& h4 y- Y* }xml_set_element_handler($xp, "elementBegin", "elementEnd");7 ]" c2 h5 `" k; P: z
xml_set_character_data_handler($xp, "characterData");
+ W  `; s& x9 V. s2 ]% W5 pxml_parser_set_option($xp, XML_OPTION_CASE_FOLDING, TRUE);3 U1 W( [1 N; z' ?) J
! x5 q8 i6 K3 H/ T
// read XML file( ^  z" O) X8 G+ ]. S+ @5 n
if (!($fp = fopen($file, "r"))) $ W2 l0 X. o* Y1 ]
{
$ L" E( Z* H9 b. z7 b3 v     die("Could not read $file");
5 H6 O9 V7 w6 c2 n  G1 e}# ^2 M% j7 W" B8 L; F! {, J# k1 n* w

9 Y: v% P7 P% }  p; ?$ u// parse data7 \. P( L$ d7 K& N! I
while ($xml = fread($fp, 4096)) % @- v% c& u: S" c3 v
{
- a6 G$ E- @8 F' G   if (!xml_parse($xp, $xml, feof($fp))) 5 i9 J2 p2 h8 J$ s; T8 [1 N' Y5 ]
   {
+ L* B  y) h4 ]  ]\t   die("XML parser error: " ./ g5 ~; g- ^2 A. `
xml_error_string(xml_get_error_code($xp)));; A) E* F! e% _! I! S
   }
" ?8 Q4 _$ ]5 W+ x! ]& l}
* |" T6 z, k" B4 ^* a% n) W4 R( b3 B* T
// destroy parser" g& F+ C; a( M3 j3 _
xml_parser_free($xp);
2 p. Q& ?( X8 R5 G& p; o3 D+ c" D, ?' Q# _9 C' ~' b0 _, ^
这段代码简单明了,其中的注释已经解释的足够清楚了。xml_parser_create()函数建立一个分析器实例,并将之赋给句柄$xp。接着再创建回调函数处理开标记和闭标记,以及二者之间的字符数据。最后,xml_parse()函数联合多次fread()调用,读取RDF文件并分析它。9 w8 n# d. F" V3 ?' [

0 l, @7 d- a5 E. o  i0 v" v3 x6 O在文档中,每次遇到开标记,开标记处理器elementBegin()就会被调用。% b" l# t- j2 d6 f

- i$ h, ?$ ~8 f// opening tag handler
# I5 W4 Y- S/ O( vfunction elementBegin($parser, $name, $attributes)
; Y' w: {# }' c: g7 u0 H{
2 ?- X  I! a3 k) t- H/ b. x7 t global $currentTag, $flag;
% Y$ x% B) Q+ N, b5 z$ Z6 b // export the name of the current tag to the global scope
, N) O8 T( l, v3 c( }: ~' _ $currentTag = $name;2 m* U( a0 Z# j  j/ `% T) W! A/ x
// if within an item block, set a flag
4 e" h, @1 g$ w' V. e$ U. X$ d if ($name == "ITEM")% U' V5 ]! X$ j6 m
{1 c% X; N8 Z& E; K0 c
\t   $flag = 1;. G0 S) i9 K* l( m- F2 k# P& ~* i8 ]1 Z
}& J$ L/ {1 q3 ?% Y& n* a
}7 O; u0 \; g4 E- A+ d% U

  l' ^; y; X4 Z' [. o* J5 S这个函数以当前标记的名称和属性作为起参数。标记名称被赋值给全局变量$currentTag。如果,这个开标记是<item>,那么把$flag变量置1。. ^2 k6 Q3 B- I. `7 @- I
, L& {# p) s4 x: X5 u
同样,如果遇到闭标记,那么闭标记处理器elementEnd()将被调用。
0 I, q% v5 _% e$ l) l  X' h
# W5 c! v' z) p! M9 ?7 W7 `! r( o3 U// closing tag handler      
) G# h+ M4 i. f+ o4 Ofunction elementEnd($parser, $name)1 @; r; _8 z) k6 ?( e) E3 {  `2 M
{
# |( t$ O/ ~  y$ ~! ~8 C global $currentTag, $flag;+ Z$ y; L7 B6 L1 ^
$currentTag = "";/ S; h! c7 O" S4 l3 g
// if exiting an item block, print a line and reset the flag
! n# x# a4 i( y( U8 y( q if ($name == "ITEM")
/ Z* a/ V6 ]2 s9 a- Y  ^. H0 j {
' ]+ M. Q1 Z7 b/ r: X* o& X; v\t   echo "<hr>";, y  I1 X  z. t) F- q5 Z
\t   $flag = 0;
8 E8 @% z! K. K }
+ E+ [6 S0 I" s$ W}
- A  T9 I/ R8 d% i
8 {- C9 V( V. |( D8 d闭标记处理函数也是以标记名称作为其参数。如果是遇到的是一个为</item>的闭标记,变量$flag的值重置为0,并把变量$currentTag的值清空。
" X6 h! }; P5 Q% x+ y1 F+ u+ @' C  c$ t3 X8 F& z
那么,如何处理标记之间的字符数据呢? 这才是我们的兴趣所在。先向字符数据处理器characterData()打个招呼吧。
! }8 w. y1 c, Y1 @; N# L& i
0 D) u3 T8 S$ ^2 O8 d! D* a% u7 |% z// character data handler
& a: h" j7 O8 J9 r3 D0 ifunction characterData($parser, $data)
! m) I/ f1 r% ?" Z$ s( L{% L0 ~* b2 ~- C4 ~- ?* V
global $currentTag, $flag;$ W. x, s. L, j( r: j7 E, v
// if within an item block, print item data
' T' t/ d$ J& i  E if (($currentTag == "TITLE" || $currentTag == "LINK" ||, b% t% g4 F8 [+ P1 X; G
$currentTag ==
5 B; J+ Y1 _; e3 x"DESCRIPTION") && $flag == 1)$ s2 [0 m. G* y2 l1 I
{
) O% d6 r0 |# k* a% \" q\t   echo "$currentTag: $data <br>";7 E! I) U0 E5 M. y
}5 W$ I9 x' i! O2 l
}
9 O( S) }2 }0 B. ]* t: R& Y  V/ r6 ^6 ~
3 \1 j5 @4 w6 e( {+ Q现在你可以看一下传给这个函数的参数,你会发现它只接收了开标记和闭标记之间的数据,而根本不知道分析器当前正在处理哪个标记。而这正事我们一开始就引入全局变量$currentTag的原因。
5 N0 B7 W, a! M
' f# y# v# T1 x3 f' i如果$flag变量的值为1,也就是说如果分析器当前处于<item></itme>区块之间,那么当前被处理的元素,不管是<title>,<link>还是<description>,数据都被打印到输出设备上(在这里,输出设备是Web浏览器),并在每个元素的输出后面加上换行符<br>。
; h3 D; o5 L- e! i$ y+ r1 c& k# _
# b7 l& K5 J4 l整个RDF文档就是以这种顺序方式处理,每发现一个<item>标记就显示一定的输出。你可以看一下下面的运行结果:
/ U( O% K2 ~4 ~. y8 i0 n1 E- }5 |. @, i  T" p1 _# g, n8 I) T
You look down on me today, tomorrow I can't let you have been

精彩评论13

二洋璜 发表于 2016-6-25 19:54:33 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
珍妨莲 发表于 2016-6-25 23:19:03 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
棣枝广 发表于 2016-6-26 14:10:53 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
登洲远 发表于 2016-6-26 23:35:05 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
zuantanduita 发表于 2016-6-26 23:38:04 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
棣枝广 发表于 2016-6-27 09:12:46 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
保庆燕 发表于 2016-6-27 09:16:56 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
汎阿青 发表于 2016-6-27 09:39:40 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
珍妨莲 发表于 2016-6-27 12:09:47 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽

关注0

粉丝6

帖子3328

发布主题
阅读排行 更多
广告位

扫描微信二维码

关注华域联盟公众号

随时了解更新最新资讯

admin@cnhackhy.com

在线客服(服务时间 9:00~18:00)

在线QQ客服

Powered by cnhackhy! © 2015-2019